@@ -5,6 +5,7 @@ package main
55import (
66 "errors"
77 "fmt"
8+ "net"
89 "os"
910 "path/filepath"
1011 "strconv"
@@ -121,13 +122,13 @@ func setupIO(process *libcontainer.Process, rootuid, rootgid int, createTTY, det
121122 // requirement that we set up anything nice for our caller or the
122123 // container.
123124 if detach {
124- // TODO: Actually set rootuid, rootgid.
125125 if err := dupStdio (process , rootuid , rootgid ); err != nil {
126126 return nil , err
127127 }
128128 return & tty {}, nil
129129 }
130130
131+ // XXX: This doesn't sit right with me. It's ugly.
131132 return createStdioPipes (process , rootuid , rootgid )
132133}
133134
@@ -180,10 +181,15 @@ type runner struct {
180181 detach bool
181182 listenFDs []* os.File
182183 pidFile string
184+ consoleSocket string
183185 container libcontainer.Container
184186 create bool
185187}
186188
189+ func (r * runner ) terminalinfo () * libcontainer.TerminalInfo {
190+ return libcontainer .NewTerminalInfo (r .container .ID ())
191+ }
192+
187193func (r * runner ) run (config * specs.Process ) (int , error ) {
188194 process , err := newProcess (* config )
189195 if err != nil {
@@ -194,16 +200,32 @@ func (r *runner) run(config *specs.Process) (int, error) {
194200 process .Env = append (process .Env , fmt .Sprintf ("LISTEN_FDS=%d" , len (r .listenFDs )), "LISTEN_PID=1" )
195201 process .ExtraFiles = append (process .ExtraFiles , r .listenFDs ... )
196202 }
203+
197204 rootuid , err := r .container .Config ().HostUID ()
198205 if err != nil {
199206 r .destroy ()
200207 return - 1 , err
201208 }
209+
202210 rootgid , err := r .container .Config ().HostGID ()
203211 if err != nil {
204212 r .destroy ()
205213 return - 1 , err
206214 }
215+
216+ detach := r .detach || r .create
217+
218+ // Check command-line for sanity.
219+ if detach && config .Terminal && r .consoleSocket == "" {
220+ r .destroy ()
221+ return - 1 , fmt .Errorf ("cannot allocate tty if runc will detach without setting console socket" )
222+ }
223+ // XXX: Should we change this?
224+ if (! detach || ! config .Terminal ) && r .consoleSocket != "" {
225+ r .destroy ()
226+ return - 1 , fmt .Errorf ("cannot use console socket if runc will not detach or allocate tty" )
227+ }
228+
207229 startFn := r .container .Start
208230 if ! r .create {
209231 startFn = r .container .Run
@@ -212,7 +234,7 @@ func (r *runner) run(config *specs.Process) (int, error) {
212234 // with detaching containers, and then we get a tty after the container has
213235 // started.
214236 handler := newSignalHandler (r .enableSubreaper )
215- tty , err := setupIO (process , rootuid , rootgid , config .Terminal , r . detach || r . create )
237+ tty , err := setupIO (process , rootuid , rootgid , config .Terminal , detach )
216238 if err != nil {
217239 r .destroy ()
218240 return - 1 , err
@@ -229,6 +251,39 @@ func (r *runner) run(config *specs.Process) (int, error) {
229251 }
230252 }
231253 defer tty .Close ()
254+
255+ if config .Terminal && detach {
256+ conn , err := net .Dial ("unix" , r .consoleSocket )
257+ if err != nil {
258+ r .terminate (process )
259+ r .destroy ()
260+ return - 1 , err
261+ }
262+ defer conn .Close ()
263+
264+ unixconn , ok := conn .(* net.UnixConn )
265+ if ! ok {
266+ r .terminate (process )
267+ r .destroy ()
268+ return - 1 , fmt .Errorf ("casting to UnixConn failed" )
269+ }
270+
271+ socket , err := unixconn .File ()
272+ if err != nil {
273+ r .terminate (process )
274+ r .destroy ()
275+ return - 1 , err
276+ }
277+ defer socket .Close ()
278+
279+ err = tty .sendtty (socket , r .terminalinfo ())
280+ if err != nil {
281+ r .terminate (process )
282+ r .destroy ()
283+ return - 1 , err
284+ }
285+ }
286+
232287 if err := tty .ClosePostStart (); err != nil {
233288 r .terminate (process )
234289 r .destroy ()
@@ -241,7 +296,7 @@ func (r *runner) run(config *specs.Process) (int, error) {
241296 return - 1 , err
242297 }
243298 }
244- if r . detach || r . create {
299+ if detach {
245300 return 0 , nil
246301 }
247302 status , err := handler .forward (process , tty )
@@ -295,6 +350,7 @@ func startContainer(context *cli.Context, spec *specs.Spec, create bool) (int, e
295350 shouldDestroy : true ,
296351 container : container ,
297352 listenFDs : listenFDs ,
353+ consoleSocket : context .String ("console-socket" ),
298354 detach : context .Bool ("detach" ),
299355 pidFile : context .String ("pid-file" ),
300356 create : create ,
0 commit comments