Browse code

Refactor exec method Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)

Michael Crosby authored on 2014/02/22 15:37:09
Showing 1 changed files
... ...
@@ -22,20 +22,10 @@ import (
22 22
 func Exec(container *libcontainer.Container, stdin io.Reader, stdout, stderr io.Writer,
23 23
 	master *os.File, logFile string, args []string) (int, error) {
24 24
 	var (
25
-		console          string
26
-		err              error
27
-		inPipe           io.WriteCloser
28
-		outPipe, errPipe io.ReadCloser
25
+		console string
26
+		err     error
29 27
 	)
30 28
 
31
-	if container.Tty {
32
-		log.Printf("setting up master and console")
33
-		master, console, err = CreateMasterAndConsole()
34
-		if err != nil {
35
-			return -1, err
36
-		}
37
-	}
38
-
39 29
 	// create a pipe so that we can syncronize with the namespaced process and
40 30
 	// pass the veth name to the child
41 31
 	r, w, err := os.Pipe()
... ...
@@ -44,16 +34,30 @@ func Exec(container *libcontainer.Container, stdin io.Reader, stdout, stderr io.
44 44
 	}
45 45
 	system.UsetCloseOnExec(r.Fd())
46 46
 
47
-	command := CreateCommand(container, console, logFile, r.Fd(), args)
48
-	if !container.Tty {
49
-		log.Printf("opening std pipes")
50
-		if inPipe, err = command.StdinPipe(); err != nil {
47
+	if container.Tty {
48
+		log.Printf("setting up master and console")
49
+		master, console, err = CreateMasterAndConsole()
50
+		if err != nil {
51 51
 			return -1, err
52 52
 		}
53
-		if outPipe, err = command.StdoutPipe(); err != nil {
53
+	}
54
+
55
+	command := CreateCommand(container, console, logFile, r.Fd(), args)
56
+
57
+	if container.Tty {
58
+		log.Printf("starting copy for tty")
59
+		go io.Copy(stdout, master)
60
+		go io.Copy(master, stdin)
61
+
62
+		state, err := SetupWindow(master, os.Stdin)
63
+		if err != nil {
64
+			command.Process.Kill()
54 65
 			return -1, err
55 66
 		}
56
-		if errPipe, err = command.StderrPipe(); err != nil {
67
+		defer term.RestoreTerminal(os.Stdin.Fd(), state)
68
+	} else {
69
+		if err := startStdCopy(command, stdin, stdout, stderr); err != nil {
70
+			command.Process.Kill()
57 71
 			return -1, err
58 72
 		}
59 73
 	}
... ...
@@ -62,7 +66,7 @@ func Exec(container *libcontainer.Container, stdin io.Reader, stdout, stderr io.
62 62
 	if err := command.Start(); err != nil {
63 63
 		return -1, err
64 64
 	}
65
-	log.Printf("writting state file")
65
+	log.Printf("writing state file")
66 66
 	if err := writePidFile(command); err != nil {
67 67
 		command.Process.Kill()
68 68
 		return -1, err
... ...
@@ -71,12 +75,9 @@ func Exec(container *libcontainer.Container, stdin io.Reader, stdout, stderr io.
71 71
 
72 72
 	// Do this before syncing with child so that no children
73 73
 	// can escape the cgroup
74
-	if container.Cgroups != nil {
75
-		log.Printf("setting up cgroups")
76
-		if err := container.Cgroups.Apply(command.Process.Pid); err != nil {
77
-			command.Process.Kill()
78
-			return -1, err
79
-		}
74
+	if err := SetupCgroups(container, command.Process.Pid); err != nil {
75
+		command.Process.Kill()
76
+		return -1, err
80 77
 	}
81 78
 	if err := InitializeNetworking(container, command.Process.Pid, w); err != nil {
82 79
 		command.Process.Kill()
... ...
@@ -88,27 +89,6 @@ func Exec(container *libcontainer.Container, stdin io.Reader, stdout, stderr io.
88 88
 	w.Close()
89 89
 	r.Close()
90 90
 
91
-	if container.Tty {
92
-		log.Printf("starting copy for tty")
93
-		go io.Copy(stdout, master)
94
-		go io.Copy(master, stdin)
95
-
96
-		state, err := SetupWindow(master, os.Stdin)
97
-		if err != nil {
98
-			command.Process.Kill()
99
-			return -1, err
100
-		}
101
-		defer term.RestoreTerminal(os.Stdin.Fd(), state)
102
-	} else {
103
-		log.Printf("starting copy for std pipes")
104
-		go func() {
105
-			defer inPipe.Close()
106
-			io.Copy(inPipe, stdin)
107
-		}()
108
-		go io.Copy(stdout, outPipe)
109
-		go io.Copy(stderr, errPipe)
110
-	}
111
-
112 91
 	log.Printf("waiting on process")
113 92
 	if err := command.Wait(); err != nil {
114 93
 		if _, ok := err.(*exec.ExitError); !ok {
... ...
@@ -119,6 +99,16 @@ func Exec(container *libcontainer.Container, stdin io.Reader, stdout, stderr io.
119 119
 	return command.ProcessState.Sys().(syscall.WaitStatus).ExitStatus(), nil
120 120
 }
121 121
 
122
+func SetupCgroups(container *libcontainer.Container, nspid int) error {
123
+	if container.Cgroups != nil {
124
+		log.Printf("setting up cgroups")
125
+		if err := container.Cgroups.Apply(nspid); err != nil {
126
+			return err
127
+		}
128
+	}
129
+	return nil
130
+}
131
+
122 132
 func InitializeNetworking(container *libcontainer.Container, nspid int, pipe io.Writer) error {
123 133
 	if container.Network != nil {
124 134
 		log.Printf("creating host network configuration type %s", container.Network.Type)
... ...
@@ -207,3 +197,29 @@ func CreateCommand(container *libcontainer.Container, console, logFile string, p
207 207
 	command.Env = container.Env
208 208
 	return command
209 209
 }
210
+
211
+func startStdCopy(command *exec.Cmd, stdin io.Reader, stdout, stderr io.Writer) error {
212
+	log.Printf("opening std pipes")
213
+	inPipe, err := command.StdinPipe()
214
+	if err != nil {
215
+		return err
216
+	}
217
+	outPipe, err := command.StdoutPipe()
218
+	if err != nil {
219
+		return err
220
+	}
221
+	errPipe, err := command.StderrPipe()
222
+	if err != nil {
223
+		return err
224
+	}
225
+
226
+	log.Printf("starting copy for std pipes")
227
+	go func() {
228
+		defer inPipe.Close()
229
+		io.Copy(inPipe, stdin)
230
+	}()
231
+	go io.Copy(stdout, outPipe)
232
+	go io.Copy(stderr, errPipe)
233
+
234
+	return nil
235
+}