Use cmd.Process.Wait instead of cmd.Wait
Issue with cmd.Wait is that it is waiting for closing pipes and if we have forked processes which inherited pipes from parent, then we need to kill them to unblock cmd.Wait. Should fix docker/docker#10303 Now idea is next: - cmd.Process.Wait for init process dead - Kill remaining processes in cgroup (pipes closed as side effect) - use cmd.Wait for waiting pipes flushed to client Signed-off-by: Alexander Morozov <lk4d4@docker.com>
This commit is contained in:
parent
cab4b9bce1
commit
39fbf0a904
|
@ -51,10 +51,20 @@ func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Wri
|
|||
}
|
||||
child.Close()
|
||||
|
||||
wait := func() (*os.ProcessState, error) {
|
||||
ps, err := command.Process.Wait()
|
||||
// we should kill all processes in cgroup when init is died if we use
|
||||
// host PID namespace
|
||||
if !container.Namespaces.Contains(libcontainer.NEWPID) {
|
||||
killAllPids(container)
|
||||
}
|
||||
return ps, err
|
||||
}
|
||||
|
||||
terminate := func(terr error) (int, error) {
|
||||
// TODO: log the errors for kill and wait
|
||||
command.Process.Kill()
|
||||
command.Wait()
|
||||
wait()
|
||||
return -1, terr
|
||||
}
|
||||
|
||||
|
@ -94,7 +104,7 @@ func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Wri
|
|||
output, err := setupCmd.CombinedOutput()
|
||||
if err != nil || setupCmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus() != 0 {
|
||||
command.Process.Kill()
|
||||
command.Wait()
|
||||
wait()
|
||||
return -1, fmt.Errorf("setup failed: %s %s", err, output)
|
||||
}
|
||||
}
|
||||
|
@ -122,16 +132,16 @@ func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Wri
|
|||
startCallback()
|
||||
}
|
||||
|
||||
if err := command.Wait(); err != nil {
|
||||
ps, err := wait()
|
||||
if err != nil {
|
||||
if _, ok := err.(*exec.ExitError); !ok {
|
||||
return -1, err
|
||||
}
|
||||
}
|
||||
if !container.Namespaces.Contains(libcontainer.NEWPID) {
|
||||
killAllPids(container)
|
||||
}
|
||||
// waiting for pipe flushing
|
||||
command.Wait()
|
||||
|
||||
waitStatus := command.ProcessState.Sys().(syscall.WaitStatus)
|
||||
waitStatus := ps.Sys().(syscall.WaitStatus)
|
||||
if waitStatus.Signaled() {
|
||||
return EXIT_SIGNAL_OFFSET + int(waitStatus.Signal()), nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue