decred.org/dcrdex@v1.0.5/client/cmd/bwctl/signal.go (about) 1 // This code is available on the terms of the project LICENSE.md file, 2 // also available online at https://blueoakcouncil.org/license/1.0.0. 3 4 package main 5 6 import ( 7 "context" 8 "fmt" 9 "os" 10 "os/signal" 11 ) 12 13 // shutdownSignaled is closed whenever shutdown is invoked through an interrupt 14 // signal. Any contexts created using withShutdownChannel are cancelled when 15 // this is closed. 16 var shutdownSignaled = make(chan struct{}) 17 18 // WithShutdownCancel creates a copy of a context that is cancelled whenever 19 // shutdown is invoked through an interrupt signal. 20 func withShutdownCancel(ctx context.Context) context.Context { 21 ctx, cancel := context.WithCancel(ctx) 22 go func() { 23 <-shutdownSignaled 24 cancel() 25 }() 26 return ctx 27 } 28 29 // ShutdownListener listens for shutdown requests and cancels all contexts 30 // created from withShutdownCancel. This function never returns and is intended 31 // to be spawned in a new goroutine. 32 func shutdownListener() { 33 interruptChannel := make(chan os.Signal, 1) 34 // Only accept a single CTRL+C. 35 signal.Notify(interruptChannel, os.Interrupt) 36 37 // Listen for the initial shutdown signal 38 sig := <-interruptChannel 39 fmt.Printf("\nReceived signal (%s). Shutting down...\n", sig) 40 41 // Cancel all contexts created from withShutdownCancel. 42 close(shutdownSignaled) 43 44 // Listen for any more shutdown signals and log that shutdown has already 45 // been signaled. 46 for { 47 <-interruptChannel 48 fmt.Println("Shutdown signaled. Already shutting down...") 49 } 50 }