diff --git a/daemon/container_init.go b/daemon/container_init.go index ae19947..d7e6d24 100644 --- a/daemon/container_init.go +++ b/daemon/container_init.go @@ -184,20 +184,18 @@ func handleExecve(s *unixsocket.Socket, cmd *Cmd, msg *unixsocket.Msg) error { DropCaps: true, SyncFunc: syncFunc, } + // starts the runner, error is handled same as wait4 to make api simple pid, err := r.Start() - if err != nil { - return sendErrorReply(s, "execve: %v", err) - } // done is to signal kill goroutine exits - done := make(chan struct{}) + killDone := make(chan struct{}) // waitDone is to signal kill goroutine to collect zombies waitDone := make(chan struct{}) // recv kill go func() { // signal done - defer close(done) + defer close(killDone) // msg must be kill recvCmd(s) // kill all @@ -206,29 +204,27 @@ func handleExecve(s *unixsocket.Socket, cmd *Cmd, msg *unixsocket.Msg) error { <-waitDone // collect zombies for { - _, err = syscall.Wait4(-1, nil, syscall.WNOHANG, nil) - if err != nil { + pid, err := syscall.Wait4(-1, nil, syscall.WNOHANG, nil) + if err != nil || pid <= 0 { break } } }() - // wait pid + // wait pid if no error encoutered for execve var wstatus syscall.WaitStatus -loop: - for { + if err == nil { _, err = syscall.Wait4(pid, &wstatus, 0, nil) - // sync with kill goroutine - close(waitDone) - if err != nil { - sendErrorReply(s, "execve: wait4 %v", err) - break loop - } + } + // sync with kill goroutine + close(waitDone) + if err != nil { + sendErrorReply(s, "execve: wait4 %v", err) + } else { switch { case wstatus.Exited(): reply := Reply{ExitStatus: wstatus.ExitStatus()} sendReply(s, &reply, nil) - break loop case wstatus.Signaled(): var status types.Status @@ -245,11 +241,12 @@ loop: } reply := Reply{Status: status} sendReply(s, &reply, nil) - break loop + default: + sendErrorReply(s, "execve: unknown status %v", wstatus) } } // wait for kill msg and reply done for finish - <-done + <-killDone return sendReply(s, &Reply{}, nil) } diff --git a/daemon/master_cmd_execve.go b/daemon/master_cmd_execve.go index 4b6bf75..81bb856 100644 --- a/daemon/master_cmd_execve.go +++ b/daemon/master_cmd_execve.go @@ -62,19 +62,18 @@ func (m *Master) Execve(done <-chan struct{}, param *ExecveParam) (<-chan types. // make sure goroutine not leaked (blocked) even if result is not consumed wait := make(chan types.Result, 1) waitDone := make(chan struct{}) - killDone := make(chan struct{}) // Wait go func() { defer close(wait) reply2, _, _ := m.recvReply() close(waitDone) - <-killDone + // done signal (should recv after kill) + m.recvReply() + // emit result after all communication finish wait <- types.Result{ ExitStatus: reply2.ExitStatus, Status: reply2.Status, } - // done signal (should recv after kill) - m.recvReply() }() // Kill (if wait is done, a kill message need to be send to collect zombies) go func() { @@ -83,7 +82,6 @@ func (m *Master) Execve(done <-chan struct{}, param *ExecveParam) (<-chan types. case <-waitDone: } m.sendCmd(&Cmd{Cmd: cmdKill}, nil) - close(killDone) }() return wait, nil }