func waitProcess(p *libcontainer.Process, t *testing.T) { _, file, line, _ := runtime.Caller(1) status, err := p.Wait() if err != nil { t.Fatalf("%s:%d: unexpected error: %s\n\n", filepath.Base(file), line, err.Error()) } if !status.Success() { t.Fatalf("%s:%d: unexpected status: %s\n\n", filepath.Base(file), line, status.String()) } }
func waitInPIDHost(p *libcontainer.Process, c libcontainer.Container) func() (*os.ProcessState, error) { return func() (*os.ProcessState, error) { pid, err := p.Pid() if err != nil { return nil, err } process, err := os.FindProcess(pid) s, err := process.Wait() if err != nil { execErr, ok := err.(*exec.ExitError) if !ok { return s, err } s = execErr.ProcessState } killCgroupProcs(c) p.Wait() return s, err } }
// forward handles the main signal event loop forwarding, resizing, or reaping depending // on the signal received. func (h *signalHandler) forward(process *libcontainer.Process) (int, error) { // make sure we know the pid of our main process so that we can return // after it dies. pid1, err := process.Pid() if err != nil { return -1, err } // perform the initial tty resize. h.tty.resize() for s := range h.signals { switch s { case syscall.SIGWINCH: h.tty.resize() case syscall.SIGCHLD: exits, err := h.reap() if err != nil { logrus.Error(err) } for _, e := range exits { logrus.WithFields(logrus.Fields{ "pid": e.pid, "status": e.status, }).Debug("process exited") if e.pid == pid1 { // call Wait() on the process even though we already have the exit // status because we must ensure that any of the go specific process // fun such as flushing pipes are complete before we return. process.Wait() return e.status, nil } } default: logrus.Debugf("sending signal to process %s", s) if err := syscall.Kill(pid1, s.(syscall.Signal)); err != nil { logrus.Error(err) } } } return -1, nil }
func (r *runner) terminate(p *libcontainer.Process) { p.Signal(syscall.SIGKILL) p.Wait() }