github.com/titanous/docker@v1.4.1/pkg/signal/trap.go (about)

     1  package signal
     2  
     3  import (
     4  	"os"
     5  	gosignal "os/signal"
     6  	"sync/atomic"
     7  	"syscall"
     8  
     9  	log "github.com/Sirupsen/logrus"
    10  )
    11  
    12  // Trap sets up a simplified signal "trap", appropriate for common
    13  // behavior expected from a vanilla unix command-line tool in general
    14  // (and the Docker engine in particular).
    15  //
    16  // * If SIGINT or SIGTERM are received, `cleanup` is called, then the process is terminated.
    17  // * If SIGINT or SIGTERM are repeated 3 times before cleanup is complete, then cleanup is
    18  // skipped and the process terminated directly.
    19  // * If "DEBUG" is set in the environment, SIGQUIT causes an exit without cleanup.
    20  //
    21  func Trap(cleanup func()) {
    22  	c := make(chan os.Signal, 1)
    23  	signals := []os.Signal{os.Interrupt, syscall.SIGTERM}
    24  	if os.Getenv("DEBUG") == "" {
    25  		signals = append(signals, syscall.SIGQUIT)
    26  	}
    27  	gosignal.Notify(c, signals...)
    28  	go func() {
    29  		interruptCount := uint32(0)
    30  		for sig := range c {
    31  			go func(sig os.Signal) {
    32  				log.Infof("Received signal '%v', starting shutdown of docker...", sig)
    33  				switch sig {
    34  				case os.Interrupt, syscall.SIGTERM:
    35  					// If the user really wants to interrupt, let him do so.
    36  					if atomic.LoadUint32(&interruptCount) < 3 {
    37  						// Initiate the cleanup only once
    38  						if atomic.AddUint32(&interruptCount, 1) == 1 {
    39  							// Call cleanup handler
    40  							cleanup()
    41  							os.Exit(0)
    42  						} else {
    43  							return
    44  						}
    45  					} else {
    46  						log.Infof("Force shutdown of docker, interrupting cleanup")
    47  					}
    48  				case syscall.SIGQUIT:
    49  				}
    50  				os.Exit(128 + int(sig.(syscall.Signal)))
    51  			}(sig)
    52  		}
    53  	}()
    54  }