1/* 2GoCleanup: kinda like atexit()... 3 4GoCleanup packages allows you to register cleanup functions. 5These are called whenever the current process receives a SIGINT or SIGTERM 6 7You can also invoke the cleanup functions by calling Cleanup(). 8 9Unfortunately, it is not possible for cleanup to intercept calls to os.Exit() and perform cleanup befor the 10process exits. Instead of os.Exit, you can use cleanup.Exit() 11 12Cleanup is especially useful when forking off external processes. You can register 13callbacks with this package to tear down these external processes. 14*/ 15 16package gocleanup 17 18import ( 19 "os" 20 "os/signal" 21 "syscall" 22) 23 24var cleanupFuncs []func() 25var capturingSignals bool 26 27//Register a cleanup function. This will be called when: 28//- a call is made to Cleanup() 29//- a call is made to Exit() 30//- the current process receives SIGINT or SIGTERM 31func Register(f func()) { 32 cleanupFuncs = append(cleanupFuncs, f) 33 if !capturingSignals { 34 capturingSignals = true 35 go func() { 36 c := make(chan os.Signal, 1) 37 signal.Notify(c, syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM) 38 39 <-c 40 Exit(1) 41 }() 42 } 43} 44 45//Cleanup invokes all registered cleanup functions 46//all registered cleanup functions are subsequently removed 47func Cleanup() { 48 for _, f := range cleanupFuncs { 49 f() 50 } 51 cleanupFuncs = []func(){} 52} 53 54//Exit invokes all registered cleanup functions, then exits 55func Exit(status int) { 56 Cleanup() 57 os.Exit(status) 58} 59