trap.go 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. package trap // import "github.com/docker/docker/cmd/dockerd/trap"
  2. import (
  3. "context"
  4. "os"
  5. "os/signal"
  6. "syscall"
  7. "github.com/containerd/log"
  8. )
  9. const (
  10. // Immediately terminate the process when this many SIGINT or SIGTERM
  11. // signals are received.
  12. forceQuitCount = 3
  13. )
  14. // Trap sets up a simplified signal "trap", appropriate for common
  15. // behavior expected from a vanilla unix command-line tool in general
  16. // (and the Docker engine in particular).
  17. //
  18. // The first time a SIGINT or SIGTERM signal is received, `cleanup` is called in
  19. // a new goroutine.
  20. //
  21. // If SIGINT or SIGTERM are received 3 times, the process is terminated
  22. // immediately with an exit code of 128 + the signal number.
  23. func Trap(cleanup func()) {
  24. c := make(chan os.Signal, forceQuitCount)
  25. signal.Notify(c, os.Interrupt, syscall.SIGTERM)
  26. go func() {
  27. var interruptCount int
  28. for sig := range c {
  29. log.G(context.TODO()).Infof("Processing signal '%v'", sig)
  30. if interruptCount < forceQuitCount {
  31. interruptCount++
  32. // Initiate the cleanup only once
  33. if interruptCount == 1 {
  34. go cleanup()
  35. }
  36. continue
  37. }
  38. log.G(context.TODO()).Info("Forcing docker daemon shutdown without cleanup; 3 interrupts received")
  39. os.Exit(128 + int(sig.(syscall.Signal)))
  40. }
  41. }()
  42. }