diff --git a/src/cmds/restic/global_debug.go b/src/cmds/restic/global_debug.go index 347e9e2c6..6e443f2a0 100644 --- a/src/cmds/restic/global_debug.go +++ b/src/cmds/restic/global_debug.go @@ -7,18 +7,29 @@ import ( "net/http" _ "net/http/pprof" "os" + "restic/errors" + + "github.com/pkg/profile" ) var ( listenMemoryProfile string + memProfilePath string + cpuProfilePath string + + prof interface { + Stop() + } ) func init() { f := cmdRoot.PersistentFlags() f.StringVar(&listenMemoryProfile, "listen-profile", "", "listen on this `address:port` for memory profiling") + f.StringVar(&memProfilePath, "mem-profile", "", "write memory profile to `dir`") + f.StringVar(&cpuProfilePath, "cpu-profile", "", "write cpu profile to `dir`") } -func runDebug() { +func runDebug() error { if listenMemoryProfile != "" { fmt.Fprintf(os.Stderr, "running memory profile HTTP server on %v\n", listenMemoryProfile) go func() { @@ -28,4 +39,22 @@ func runDebug() { } }() } + + if memProfilePath != "" && cpuProfilePath != "" { + return errors.Fatal("only one profile (memory or CPU) may be activated at the same time") + } + + if memProfilePath != "" { + prof = profile.Start(profile.Quiet, profile.MemProfile, profile.ProfilePath(memProfilePath)) + } else if memProfilePath != "" { + prof = profile.Start(profile.Quiet, profile.CPUProfile, profile.ProfilePath(memProfilePath)) + } + + return nil +} + +func shutdownDebug() { + if prof != nil { + prof.Stop() + } } diff --git a/src/cmds/restic/global_release.go b/src/cmds/restic/global_release.go index 88b639074..0a3bc8f1b 100644 --- a/src/cmds/restic/global_release.go +++ b/src/cmds/restic/global_release.go @@ -3,4 +3,7 @@ package main // runDebug is a noop without the debug tag. -func runDebug() {} +func runDebug() error { return nil } + +// shutdownDebug is a noop without the debug tag. +func shutdownDebug() {} diff --git a/src/cmds/restic/main.go b/src/cmds/restic/main.go index 6e5a0b746..a4d162679 100644 --- a/src/cmds/restic/main.go +++ b/src/cmds/restic/main.go @@ -25,8 +25,11 @@ directories in an encrypted repository stored on different backends. // run the debug functions for all subcommands (if build tag "debug" is // enabled) - PersistentPreRun: func(*cobra.Command, []string) { - runDebug() + PersistentPreRunE: func(*cobra.Command, []string) error { + return runDebug() + }, + PersistentPostRun: func(*cobra.Command, []string) { + shutdownDebug() }, }