github.com/moby/docker@v26.1.3+incompatible/cmd/dockerd/trap/trap.go (about)

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