diff options
author | Nicolas Lacasse <nlacasse@google.com> | 2018-10-08 20:47:47 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-10-08 20:48:54 -0700 |
commit | ae5122eb87b5b453d51b70cffe2a253333af9eb4 (patch) | |
tree | caf0bbe4cfb6695d85d0b9f681dae64992d2b149 | |
parent | b8048f75daa2ec13059162cb421236f99e5e4a0e (diff) |
Job control signals must be sent to all processes in the FG process group.
We were previously only sending to the originator of the process group.
Integration test was changed to test this behavior. It fails without the
corresponding code change.
PiperOrigin-RevId: 216297263
Change-Id: I7e41cfd6bdd067f4b9dc215e28f555fb5088916f
-rw-r--r-- | runsc/boot/loader.go | 19 | ||||
-rw-r--r-- | runsc/test/integration/exec_test.go | 9 |
2 files changed, 18 insertions, 10 deletions
diff --git a/runsc/boot/loader.go b/runsc/boot/loader.go index c419b366f..5716ef217 100644 --- a/runsc/boot/loader.go +++ b/runsc/boot/loader.go @@ -698,8 +698,6 @@ func newEmptyNetworkStack(conf *Config, clock tcpip.Clock) (inet.Stack, error) { // sendToFGProcess is true, then the signal will be sent to the foreground // process group in the same session that PID belongs to. func (l *Loader) signalProcess(cid string, pid, signo int32, sendToFGProcess bool) error { - si := arch.SignalInfo{Signo: signo} - if pid <= 0 { return fmt.Errorf("failed to signal container %q PID %d: PID must be positive", cid, pid) } @@ -718,7 +716,7 @@ func (l *Loader) signalProcess(cid string, pid, signo int32, sendToFGProcess boo if !sendToFGProcess { // Send signal directly to exec process. - return ep.tg.SendSignal(&si) + return ep.tg.SendSignal(&arch.SignalInfo{Signo: signo}) } // Lookup foreground process group from the TTY for the given process, @@ -731,11 +729,20 @@ func (l *Loader) signalProcess(cid string, pid, signo int32, sendToFGProcess boo // No foreground process group has been set. Signal the // original thread group. log.Warningf("No foreground process group for container %q and PID %d. Sending signal directly to PID %d.", cid, pid, pid) - return ep.tg.SendSignal(&si) + return ep.tg.SendSignal(&arch.SignalInfo{Signo: signo}) } - // Send the signal. - return pg.Originator().SendSignal(&si) + // Send the signal to all processes in the process group. + var lastErr error + for _, tg := range l.k.TaskSet().Root.ThreadGroups() { + if tg.ProcessGroup() != pg { + continue + } + if err := tg.SendSignal(&arch.SignalInfo{Signo: signo}); err != nil { + lastErr = err + } + } + return lastErr } // signalContainer sends a signal to the root container process, or to all diff --git a/runsc/test/integration/exec_test.go b/runsc/test/integration/exec_test.go index 014254aab..d08140ad3 100644 --- a/runsc/test/integration/exec_test.go +++ b/runsc/test/integration/exec_test.go @@ -81,16 +81,17 @@ func TestExecJobControl(t *testing.T) { } defer ptmx.Close() - // Call "sleep 100" in the shell. - if _, err := ptmx.Write([]byte("sleep 100\n")); err != nil { + // Call "sleep 100 | cat" in the shell. We pipe to cat so that there + // will be two processes in the foreground process group. + if _, err := ptmx.Write([]byte("sleep 100 | cat\n")); err != nil { t.Fatalf("error writing to pty: %v", err) } // Give shell a few seconds to start executing the sleep. time.Sleep(2 * time.Second) - // Send a ^C to the pty, which should kill sleep, but not the shell. - // \x03 is ASCII "end of text", which is the same as ^C. + // Send a ^C to the pty, which should kill sleep and cat, but not the + // shell. \x03 is ASCII "end of text", which is the same as ^C. if _, err := ptmx.Write([]byte{'\x03'}); err != nil { t.Fatalf("error writing to pty: %v", err) } |