Skip to content

Instantly share code, notes, and snippets.

@paulja
Created May 7, 2025 17:10
Show Gist options
  • Save paulja/b55c33677646a44290045897b53562ef to your computer and use it in GitHub Desktop.
Save paulja/b55c33677646a44290045897b53562ef to your computer and use it in GitHub Desktop.
Go Dump Goroutines on Exit
package main
import (
"fmt"
"os"
"os/signal"
"runtime"
"syscall"
"time"
)
func main() {
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGINT, syscall.SIGQUIT)
cancel := make(chan bool)
go func() {
fmt.Print("running")
for {
<-time.After(time.Second)
fmt.Print(".")
}
}()
go func() {
<-sig
fmt.Printf("\nstopping...\n")
buf := make([]byte, 1<<20)
n := runtime.Stack(buf, true)
fmt.Printf("\n*** goroutine dump\n%s\n*** end\n", buf[:n])
cancel <- true
}()
<-cancel
fmt.Println("done")
}
@paulja
Copy link
Author

paulja commented May 7, 2025

The output of this prints something like:

% go run main.go
running..^C
stopping...

*** goroutine dump...
goroutine 8 [running]:
main.main.func2()
        /Users/paul/Downloads/main.go:27 +0x7c
created by main.main in goroutine 1
        /Users/paul/Downloads/main.go:23 +0xd3

goroutine 1 [chan receive]:
main.main()
        /Users/paul/Downloads/main.go:31 +0xdf

goroutine 17 [syscall]:
os/signal.signal_recv()
        /usr/local/Cellar/go/1.24.3/libexec/src/runtime/sigqueue.go:149 +0x25
os/signal.loop()
        /usr/local/Cellar/go/1.24.3/libexec/src/os/signal/signal_unix.go:23 +0x13
created by os/signal.Notify.func1.1 in goroutine 1
        /usr/local/Cellar/go/1.24.3/libexec/src/os/signal/signal.go:152 +0x1f

goroutine 7 [chan receive]:
main.main.func1()
        /Users/paul/Downloads/main.go:19 +0x5e
created by main.main in goroutine 1
        /Users/paul/Downloads/main.go:16 +0x85

*** end
done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment