mirror of
https://github.com/containers/podman.git
synced 2025-10-17 03:04:21 +08:00

due to a change in golang-1.14 and it's changes to make go funcs with tight loops preemptive, signals are now getting "through" that never were before. From the golang-1.14 announce: Goroutines are now asynchronously preemptible. As a result, loops without function calls no longer potentially deadlock the scheduler or significantly delay garbage collection. This is supported on all platforms except windows/arm, darwin/arm, js/wasm, and plan9/*. A consequence of the implementation of preemption is that on Unix systems, including Linux and macOS systems, programs built with Go 1.14 will receive more signals than programs built with earlier releases. This means that programs that use packages like syscall or golang.org/x/sys/unix will see more slow system calls fail with EINTR errors. Those programs will have to handle those errors in some way, most likely looping to try the system call again. For more information about this see man 7 signal for Linux systems or similar documentation for other systems. Fixes #5483 Signed-off-by: Brent Baude <bbaude@redhat.com>
46 lines
1.3 KiB
Go
46 lines
1.3 KiB
Go
package adapter
|
|
|
|
import (
|
|
"os"
|
|
"syscall"
|
|
|
|
"github.com/containers/libpod/libpod"
|
|
"github.com/containers/libpod/pkg/signal"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// ProxySignals ...
|
|
func ProxySignals(ctr *libpod.Container) {
|
|
sigBuffer := make(chan os.Signal, 128)
|
|
signal.CatchAll(sigBuffer)
|
|
|
|
logrus.Debugf("Enabling signal proxying")
|
|
|
|
go func() {
|
|
for s := range sigBuffer {
|
|
// Ignore SIGCHLD and SIGPIPE - these are mostly likely
|
|
// intended for the podman command itself.
|
|
// SIGURG was added because of golang 1.14 and its preemptive changes
|
|
// causing more signals to "show up".
|
|
// https://github.com/containers/libpod/issues/5483
|
|
if s == syscall.SIGCHLD || s == syscall.SIGPIPE || s == syscall.SIGURG {
|
|
continue
|
|
}
|
|
|
|
if err := ctr.Kill(uint(s.(syscall.Signal))); err != nil {
|
|
// If the container dies, and we find out here,
|
|
// we need to forward that one signal to
|
|
// ourselves so that it is not lost, and then
|
|
// we terminate the proxy and let the defaults
|
|
// play out.
|
|
logrus.Errorf("Error forwarding signal %d to container %s: %v", s, ctr.ID(), err)
|
|
signal.StopCatch(sigBuffer)
|
|
if err := syscall.Kill(syscall.Getpid(), s.(syscall.Signal)); err != nil {
|
|
logrus.Errorf("failed to kill pid %d", syscall.Getpid())
|
|
}
|
|
return
|
|
}
|
|
}
|
|
}()
|
|
}
|