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:
Alexander Morozov 2015-01-23 14:17:33 -08:00
parent cab4b9bce1
commit 39fbf0a904
1 changed files with 17 additions and 7 deletions

View File

@ -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
}