diff --git a/.gitignore b/.gitignore index fbc46df64..de29cc028 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ protos/google/* *test_bolt.db *.coverprofile +*.log /release/ *.swp diff --git a/cmd/captplanet/main.go b/cmd/captplanet/main.go index 945732117..c75bbd3bc 100644 --- a/cmd/captplanet/main.go +++ b/cmd/captplanet/main.go @@ -4,10 +4,18 @@ package main import ( + "fmt" + "io/ioutil" + "os" + "os/signal" "path/filepath" + "runtime" + "syscall" + "time" "github.com/spf13/cobra" monkit "gopkg.in/spacemonkeygo/monkit.v2" + "storj.io/storj/internal/memory" "storj.io/storj/pkg/process" ) @@ -23,6 +31,8 @@ var ( ) func main() { + go dumpHandler() + // process.Exec will load this for this command. runCmd.Flags().String("config", filepath.Join(defaultConfDir, "config.yaml"), "path to configuration") @@ -30,3 +40,33 @@ func main() { filepath.Join(defaultConfDir, "setup.yaml"), "path to configuration") process.Exec(rootCmd) } + +// dumpHandler listens for Ctrl+\ on Unix +func dumpHandler() { + if runtime.GOOS == "windows" { + // unsupported on Windows + return + } + + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGQUIT) + for range sigs { + dumpGoroutines() + } +} + +func dumpGoroutines() { + buf := make([]byte, memory.MB) + n := runtime.Stack(buf, true) + + p := time.Now().Format("dump-2006-01-02T15-04-05.999999999.log") + if abs, err := filepath.Abs(p); err == nil { + p = abs + } + fmt.Fprintf(os.Stderr, "Writing stack traces to \"%v\"\n", p) + + err := ioutil.WriteFile(p, buf[:n], 0644) + if err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + } +}