@@ -5,6 +5,7 @@ package libcontainer
55import (
66 "bytes"
77 "encoding/json"
8+ "errors"
89 "fmt"
910 "io"
1011 "io/ioutil"
@@ -267,20 +268,71 @@ func (c *linuxContainer) Exec() error {
267268
268269func (c * linuxContainer ) exec () error {
269270 path := filepath .Join (c .root , execFifoFilename )
270- f , err := os .OpenFile (path , os .O_RDONLY , 0 )
271- if err != nil {
272- return newSystemErrorWithCause (err , "open exec fifo for reading" )
271+
272+ fifoOpen := make (chan struct {})
273+ select {
274+ case <- awaitProcessExit (c .initProcess .pid (), fifoOpen ):
275+ return errors .New ("container process is already dead" )
276+ case result := <- awaitFifoOpen (path ):
277+ close (fifoOpen )
278+ if result .err != nil {
279+ return result .err
280+ }
281+ f := result .file
282+ defer f .Close ()
283+ if err := readFromExecFifo (f ); err != nil {
284+ return err
285+ }
286+ return os .Remove (path )
273287 }
274- defer f .Close ()
275- data , err := ioutil .ReadAll (f )
288+ }
289+
290+ func readFromExecFifo (execFifo io.Reader ) error {
291+ data , err := ioutil .ReadAll (execFifo )
276292 if err != nil {
277293 return err
278294 }
279- if len (data ) > 0 {
280- os .Remove (path )
281- return nil
295+ if len (data ) <= 0 {
296+ return fmt .Errorf ("cannot start an already running container" )
282297 }
283- return fmt .Errorf ("cannot start an already running container" )
298+ return nil
299+ }
300+
301+ func awaitProcessExit (pid int , exit <- chan struct {}) <- chan struct {} {
302+ isDead := make (chan struct {})
303+ go func () {
304+ for {
305+ select {
306+ case <- exit :
307+ return
308+ case <- time .After (time .Millisecond * 100 ):
309+ stat , err := system .Stat (pid )
310+ if err != nil || stat .State == system .Zombie {
311+ close (isDead )
312+ return
313+ }
314+ }
315+ }
316+ }()
317+ return isDead
318+ }
319+
320+ func awaitFifoOpen (path string ) <- chan openResult {
321+ fifoOpened := make (chan openResult )
322+ go func () {
323+ f , err := os .OpenFile (path , os .O_RDONLY , 0 )
324+ if err != nil {
325+ fifoOpened <- openResult {err : newSystemErrorWithCause (err , "open exec fifo for reading" )}
326+ return
327+ }
328+ fifoOpened <- openResult {file : f }
329+ }()
330+ return fifoOpened
331+ }
332+
333+ type openResult struct {
334+ file * os.File
335+ err error
284336}
285337
286338func (c * linuxContainer ) start (process * Process , isInit bool ) error {
0 commit comments