From 2f93ddbe6276d37b2a348e71868e2e2a25909801 Mon Sep 17 00:00:00 2001 From: Nicolas Lacasse Date: Thu, 10 Aug 2023 15:31:35 -0700 Subject: [PATCH] Create kernel.SendExternalSignalProcessGroup and use it in boot/loader.go This will send a signal to all processes (ThreadGroups) in a ProcessGroup. PiperOrigin-RevId: 555679773 --- pkg/sentry/kernel/kernel.go | 22 ++++++++++++++++++++++ runsc/boot/loader.go | 14 +++----------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/pkg/sentry/kernel/kernel.go b/pkg/sentry/kernel/kernel.go index 04d241996..34a8efbf1 100644 --- a/pkg/sentry/kernel/kernel.go +++ b/pkg/sentry/kernel/kernel.go @@ -1213,6 +1213,7 @@ func (k *Kernel) SendExternalSignal(info *linux.SignalInfo, context string) { } // SendExternalSignalThreadGroup injects a signal into an specific ThreadGroup. +// // This function doesn't skip signals like SendExternalSignal does. func (k *Kernel) SendExternalSignalThreadGroup(tg *ThreadGroup, info *linux.SignalInfo) error { k.extMu.Lock() @@ -1220,6 +1221,27 @@ func (k *Kernel) SendExternalSignalThreadGroup(tg *ThreadGroup, info *linux.Sign return tg.SendSignal(info) } +// SendExternalSignalProcessGroup sends a signal to all ThreadGroups in the +// given process group. +// +// This function doesn't skip signals like SendExternalSignal does. +func (k *Kernel) SendExternalSignalProcessGroup(pg *ProcessGroup, info *linux.SignalInfo) error { + k.extMu.Lock() + defer k.extMu.Unlock() + // If anything goes wrong, we'll return the error, but still try our + // best to deliver to other processes in the group. + var firstErr error + for _, tg := range k.TaskSet().Root.ThreadGroups() { + if tg.ProcessGroup() != pg { + continue + } + if err := tg.SendSignal(info); err != nil && firstErr == nil { + firstErr = err + } + } + return firstErr +} + // SendContainerSignal sends the given signal to all processes inside the // namespace that match the given container ID. func (k *Kernel) SendContainerSignal(cid string, info *linux.SignalInfo) error { diff --git a/runsc/boot/loader.go b/runsc/boot/loader.go index 69d25d6c9..4cd3b5273 100644 --- a/runsc/boot/loader.go +++ b/runsc/boot/loader.go @@ -1414,23 +1414,15 @@ func (l *Loader) signalForegrondProcessGroup(cid string, tgid kernel.ThreadID, s return fmt.Errorf("no TTY attached") } pg := tty.ForegroundProcessGroup() + si := &linux.SignalInfo{Signo: signo} if pg == nil { // 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, tgid, tgid) - return l.k.SendExternalSignalThreadGroup(tg, &linux.SignalInfo{Signo: signo}) + return l.k.SendExternalSignalThreadGroup(tg, 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 := l.k.SendExternalSignalThreadGroup(tg, &linux.SignalInfo{Signo: signo}); err != nil { - lastErr = err - } - } - return lastErr + return l.k.SendExternalSignalProcessGroup(pg, si) } // signalAllProcesses that belong to specified container. It's a noop if the