forked from TrueCloudLab/rclone
lib/atexit: factor from cmd so it can be used by backend/cache #1946
This commit is contained in:
parent
dbabb18b0c
commit
fa500e6d21
3 changed files with 50 additions and 48 deletions
|
@ -1,45 +0,0 @@
|
||||||
package cmd
|
|
||||||
|
|
||||||
// Atexit handling
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/ncw/rclone/fs"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
atExitFns []func()
|
|
||||||
atExitOnce sync.Once
|
|
||||||
atExitRegisterOnce sync.Once
|
|
||||||
)
|
|
||||||
|
|
||||||
// AtExit registers a function to be added on exit
|
|
||||||
func AtExit(fn func()) {
|
|
||||||
atExitFns = append(atExitFns, fn)
|
|
||||||
// Run AtExit handlers on SIGINT or SIGTERM so everything gets
|
|
||||||
// tidied up properly
|
|
||||||
atExitRegisterOnce.Do(func() {
|
|
||||||
go func() {
|
|
||||||
ch := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(ch, os.Interrupt) // syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT
|
|
||||||
sig := <-ch
|
|
||||||
fs.Infof(nil, "Signal received: %s", sig)
|
|
||||||
runAtExitFunctions()
|
|
||||||
fs.Infof(nil, "Exiting...")
|
|
||||||
os.Exit(0)
|
|
||||||
}()
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Runs all the AtExit functions if they haven't been run already
|
|
||||||
func runAtExitFunctions() {
|
|
||||||
atExitOnce.Do(func() {
|
|
||||||
for _, fn := range atExitFns {
|
|
||||||
fn()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"github.com/ncw/rclone/fs/fserrors"
|
"github.com/ncw/rclone/fs/fserrors"
|
||||||
"github.com/ncw/rclone/fs/fspath"
|
"github.com/ncw/rclone/fs/fspath"
|
||||||
fslog "github.com/ncw/rclone/fs/log"
|
fslog "github.com/ncw/rclone/fs/log"
|
||||||
|
"github.com/ncw/rclone/lib/atexit"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Globals
|
// Globals
|
||||||
|
@ -105,7 +106,7 @@ and configuration walkthroughs.
|
||||||
`,
|
`,
|
||||||
PersistentPostRun: func(cmd *cobra.Command, args []string) {
|
PersistentPostRun: func(cmd *cobra.Command, args []string) {
|
||||||
fs.Debugf("rclone", "Version %q finishing with parameters %q", fs.Version, os.Args)
|
fs.Debugf("rclone", "Version %q finishing with parameters %q", fs.Version, os.Args)
|
||||||
runAtExitFunctions()
|
atexit.Run()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,14 +396,14 @@ func initConfig() {
|
||||||
fs.CountError(err)
|
fs.CountError(err)
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
AtExit(func() {
|
atexit.Register(func() {
|
||||||
pprof.StopCPUProfile()
|
pprof.StopCPUProfile()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup memory profiling if desired
|
// Setup memory profiling if desired
|
||||||
if *memProfile != "" {
|
if *memProfile != "" {
|
||||||
AtExit(func() {
|
atexit.Register(func() {
|
||||||
fs.Infof(nil, "Saving Memory profile %q\n", *memProfile)
|
fs.Infof(nil, "Saving Memory profile %q\n", *memProfile)
|
||||||
f, err := os.Create(*memProfile)
|
f, err := os.Create(*memProfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
46
lib/atexit/atexit.go
Normal file
46
lib/atexit/atexit.go
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
// Package atexit provides handling for functions you want called when
|
||||||
|
// the program exits unexpectedly due to a signal.
|
||||||
|
//
|
||||||
|
// You should also make sure you call Run in the normal exit path.
|
||||||
|
package atexit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/ncw/rclone/fs"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
fns []func()
|
||||||
|
exitOnce sync.Once
|
||||||
|
registerOnce sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
// Register a function to be called on exit
|
||||||
|
func Register(fn func()) {
|
||||||
|
fns = append(fns, fn)
|
||||||
|
// Run AtExit handlers on SIGINT or SIGTERM so everything gets
|
||||||
|
// tidied up properly
|
||||||
|
registerOnce.Do(func() {
|
||||||
|
go func() {
|
||||||
|
ch := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(ch, os.Interrupt) // syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT
|
||||||
|
sig := <-ch
|
||||||
|
fs.Infof(nil, "Signal received: %s", sig)
|
||||||
|
Run()
|
||||||
|
fs.Infof(nil, "Exiting...")
|
||||||
|
os.Exit(0)
|
||||||
|
}()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run all the at exit functions if they haven't been run already
|
||||||
|
func Run() {
|
||||||
|
exitOnce.Do(func() {
|
||||||
|
for _, fn := range fns {
|
||||||
|
fn()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue