cmd/dockerd: use default SIGQUIT behaviour
dockerd handles SIGQUIT by dumping all goroutine stacks to standard
error and exiting. In contrast, the Go runtime's default SIGQUIT
behaviour... dumps all goroutine stacks to standard error and exits.
The default SIGQUIT behaviour is implemented directly in the runtime's
signal handler, and so is both more robust to bugs in the Go runtime and
does not perturb the state of the process to anywhere near same degree
as dumping goroutine stacks from a user goroutine. The only notable
difference from a user's perspective is that the process exits with
status 2 instead of 128+SIGQUIT.
Signed-off-by: Cory Snider <csnider@mirantis.com>
(cherry picked from commit 0867d3173c
)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
ebedb1c496
commit
d9bdb61992
2 changed files with 4 additions and 12 deletions
|
@ -3,11 +3,9 @@ package trap // import "github.com/docker/docker/cmd/dockerd/trap"
|
|||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
gosignal "os/signal"
|
||||
"os/signal"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
|
||||
"github.com/docker/docker/pkg/stack"
|
||||
)
|
||||
|
||||
// Trap sets up a simplified signal "trap", appropriate for common
|
||||
|
@ -17,7 +15,6 @@ import (
|
|||
// - If SIGINT or SIGTERM are received, `cleanup` is called, then the process is terminated.
|
||||
// - If SIGINT or SIGTERM are received 3 times before cleanup is complete, then cleanup is
|
||||
// skipped and the process is terminated immediately (allows force quit of stuck daemon)
|
||||
// - A SIGQUIT always causes an exit without cleanup, with a goroutine dump preceding exit.
|
||||
// - Ignore SIGPIPE events. These are generated by systemd when journald is restarted while
|
||||
// the docker daemon is not restarted and also running under systemd.
|
||||
// Fixes https://github.com/docker/docker/issues/19728
|
||||
|
@ -25,9 +22,8 @@ func Trap(cleanup func(), logger interface {
|
|||
Info(args ...interface{})
|
||||
}) {
|
||||
c := make(chan os.Signal, 1)
|
||||
// we will handle INT, TERM, QUIT, SIGPIPE here
|
||||
signals := []os.Signal{os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGPIPE}
|
||||
gosignal.Notify(c, signals...)
|
||||
// we will handle INT, TERM, SIGPIPE here
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGPIPE)
|
||||
go func() {
|
||||
interruptCount := uint32(0)
|
||||
for sig := range c {
|
||||
|
@ -52,11 +48,8 @@ func Trap(cleanup func(), logger interface {
|
|||
// 3 SIGTERM/INT signals received; force exit without cleanup
|
||||
logger.Info("Forcing docker daemon shutdown without cleanup; 3 interrupts received")
|
||||
}
|
||||
case syscall.SIGQUIT:
|
||||
stack.Dump()
|
||||
logger.Info("Forcing docker daemon shutdown without cleanup on SIGQUIT")
|
||||
}
|
||||
// for the SIGINT/TERM, and SIGQUIT non-clean shutdown case, exit with 128 + signal #
|
||||
// for the SIGINT/TERM non-clean shutdown case, exit with 128 + signal #
|
||||
os.Exit(128 + int(sig.(syscall.Signal)))
|
||||
}(sig)
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ func TestTrap(t *testing.T) {
|
|||
multiple bool
|
||||
}{
|
||||
{"TERM", syscall.SIGTERM, false},
|
||||
{"QUIT", syscall.SIGQUIT, true},
|
||||
{"INT", os.Interrupt, false},
|
||||
{"TERM", syscall.SIGTERM, true},
|
||||
{"INT", os.Interrupt, true},
|
||||
|
|
Loading…
Reference in a new issue