github.com/advanderveer/restic@v0.8.1-0.20171209104529-42a8c19aaea6/cmd/restic/cleanup.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "os" 6 "os/signal" 7 "sync" 8 "syscall" 9 10 "github.com/restic/restic/internal/debug" 11 ) 12 13 var cleanupHandlers struct { 14 sync.Mutex 15 list []func() error 16 done bool 17 ch chan os.Signal 18 } 19 20 var stderr = os.Stderr 21 22 func init() { 23 cleanupHandlers.ch = make(chan os.Signal) 24 go CleanupHandler(cleanupHandlers.ch) 25 InstallSignalHandler() 26 } 27 28 // InstallSignalHandler listens for SIGINT, and triggers the cleanup handlers. 29 func InstallSignalHandler() { 30 signal.Notify(cleanupHandlers.ch, syscall.SIGINT) 31 } 32 33 // SuspendSignalHandler removes the signal handler for SIGINT. 34 func SuspendSignalHandler() { 35 signal.Reset(syscall.SIGINT) 36 } 37 38 // AddCleanupHandler adds the function f to the list of cleanup handlers so 39 // that it is executed when all the cleanup handlers are run, e.g. when SIGINT 40 // is received. 41 func AddCleanupHandler(f func() error) { 42 cleanupHandlers.Lock() 43 defer cleanupHandlers.Unlock() 44 45 // reset the done flag for integration tests 46 cleanupHandlers.done = false 47 48 cleanupHandlers.list = append(cleanupHandlers.list, f) 49 } 50 51 // RunCleanupHandlers runs all registered cleanup handlers 52 func RunCleanupHandlers() { 53 cleanupHandlers.Lock() 54 defer cleanupHandlers.Unlock() 55 56 if cleanupHandlers.done { 57 return 58 } 59 cleanupHandlers.done = true 60 61 for _, f := range cleanupHandlers.list { 62 err := f() 63 if err != nil { 64 fmt.Fprintf(stderr, "error in cleanup handler: %v\n", err) 65 } 66 } 67 cleanupHandlers.list = nil 68 } 69 70 // CleanupHandler handles the SIGINT signals. 71 func CleanupHandler(c <-chan os.Signal) { 72 for s := range c { 73 debug.Log("signal %v received, cleaning up", s) 74 fmt.Fprintf(stderr, "%ssignal %v received, cleaning up\n", ClearLine(), s) 75 76 code := 0 77 if s != syscall.SIGINT { 78 code = 1 79 } 80 81 Exit(code) 82 } 83 } 84 85 // Exit runs the cleanup handlers and then terminates the process with the 86 // given exit code. 87 func Exit(code int) { 88 RunCleanupHandlers() 89 os.Exit(code) 90 }