Browse code

Fix stdin handling in engine.Sender and engine.Receiver

This introduces a superficial change to the Beam API:

* `beam.SendPipe` is renamed to the more accurate `beam.SendRPipe`
* `beam.SendWPipe` is introduced as a mirror to `SendRPipe`

There is no other change in the beam API.

Docker-DCO-1.1-Signed-off-by: Solomon Hykes <solomon@docker.com> (github: shykes)

Solomon Hykes authored on 2014/05/10 07:39:55
Showing 5 changed files
... ...
@@ -92,17 +92,17 @@ func (rcv *Receiver) Run() error {
92 92
 		}
93 93
 		cmd := data.Message(p).Get("cmd")
94 94
 		job := rcv.Engine.Job(cmd[0], cmd[1:]...)
95
-		stdout, err := beam.SendPipe(peer, data.Empty().Set("cmd", "log", "stdout").Bytes())
95
+		stdout, err := beam.SendRPipe(peer, data.Empty().Set("cmd", "log", "stdout").Bytes())
96 96
 		if err != nil {
97 97
 			return err
98 98
 		}
99 99
 		job.Stdout.Add(stdout)
100
-		stderr, err := beam.SendPipe(peer, data.Empty().Set("cmd", "log", "stderr").Bytes())
100
+		stderr, err := beam.SendRPipe(peer, data.Empty().Set("cmd", "log", "stderr").Bytes())
101 101
 		if err != nil {
102 102
 			return err
103 103
 		}
104 104
 		job.Stderr.Add(stderr)
105
-		stdin, err := beam.SendPipe(peer, data.Empty().Set("cmd", "log", "stdin").Bytes())
105
+		stdin, err := beam.SendWPipe(peer, data.Empty().Set("cmd", "log", "stdin").Bytes())
106 106
 		if err != nil {
107 107
 			return err
108 108
 		}
... ...
@@ -29,17 +29,48 @@ type ReceiveSender interface {
29 29
 	Sender
30 30
 }
31 31
 
32
-func SendPipe(dst Sender, data []byte) (*os.File, error) {
32
+const (
33
+	R int = 1 << (32 - 1 - iota)
34
+	W
35
+)
36
+
37
+func sendPipe(dst Sender, data []byte, mode int) (*os.File, error) {
33 38
 	r, w, err := os.Pipe()
34 39
 	if err != nil {
35 40
 		return nil, err
36 41
 	}
37
-	if err := dst.Send(data, r); err != nil {
38
-		r.Close()
39
-		w.Close()
42
+	var (
43
+		remote *os.File
44
+		local  *os.File
45
+	)
46
+	if mode == R {
47
+		remote = r
48
+		local = w
49
+	} else if mode == W {
50
+		remote = w
51
+		local = r
52
+	}
53
+	if err := dst.Send(data, remote); err != nil {
54
+		local.Close()
55
+		remote.Close()
40 56
 		return nil, err
41 57
 	}
42
-	return w, nil
58
+	return local, nil
59
+
60
+}
61
+
62
+// SendRPipe create a pipe and sends its *read* end attached in a beam message
63
+// to `dst`, with `data` as the message payload.
64
+// It returns the *write* end of the pipe, or an error.
65
+func SendRPipe(dst Sender, data []byte) (*os.File, error) {
66
+	return sendPipe(dst, data, R)
67
+}
68
+
69
+// SendWPipe create a pipe and sends its *read* end attached in a beam message
70
+// to `dst`, with `data` as the message payload.
71
+// It returns the *write* end of the pipe, or an error.
72
+func SendWPipe(dst Sender, data []byte) (*os.File, error) {
73
+	return sendPipe(dst, data, W)
43 74
 }
44 75
 
45 76
 func SendConn(dst Sender, data []byte) (conn *UnixConn, err error) {
... ...
@@ -257,12 +257,12 @@ func Handlers(sink beam.Sender) (*beam.UnixConn, error) {
257 257
 				if handler == nil {
258 258
 					return
259 259
 				}
260
-				stdout, err := beam.SendPipe(conn, data.Empty().Set("cmd", "log", "stdout").Set("fromcmd", cmd...).Bytes())
260
+				stdout, err := beam.SendRPipe(conn, data.Empty().Set("cmd", "log", "stdout").Set("fromcmd", cmd...).Bytes())
261 261
 				if err != nil {
262 262
 					return
263 263
 				}
264 264
 				defer stdout.Close()
265
-				stderr, err := beam.SendPipe(conn, data.Empty().Set("cmd", "log", "stderr").Set("fromcmd", cmd...).Bytes())
265
+				stderr, err := beam.SendRPipe(conn, data.Empty().Set("cmd", "log", "stderr").Set("fromcmd", cmd...).Bytes())
266 266
 				if err != nil {
267 267
 					return
268 268
 				}
... ...
@@ -272,7 +272,7 @@ func CmdPrint(args []string, stdout, stderr io.Writer, in beam.Receiver, out bea
272 272
 		}
273 273
 		// Skip commands
274 274
 		if a != nil && data.Message(payload).Get("cmd") == nil {
275
-			dup, err := beam.SendPipe(out, payload)
275
+			dup, err := beam.SendRPipe(out, payload)
276 276
 			if err != nil {
277 277
 				a.Close()
278 278
 				return
... ...
@@ -78,7 +78,7 @@ func (route *Route) Tee(dst Sender) *Route {
78 78
 			return inner(payload, attachment)
79 79
 		}
80 80
 		// Setup the tee
81
-		w, err := SendPipe(dst, payload)
81
+		w, err := SendRPipe(dst, payload)
82 82
 		if err != nil {
83 83
 			return err
84 84
 		}