Skip to content

Commit

Permalink
save goroutine stacks to a file on crash
Browse files Browse the repository at this point in the history
  • Loading branch information
cenkalti committed Mar 29, 2019
1 parent 92a101a commit a064d3a
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 34 deletions.
44 changes: 44 additions & 0 deletions torrent/healthcheck.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package torrent

import (
"io/ioutil"
"runtime"
"time"
)

// checkTorrent pings the torrent run loop periodically and crashes the program if a torrent does not respond in
// specified timeout. This is not a good behavior for a production program but it helps to find deadlocks easily,
// at least while developing.
func (s *Session) checkTorrent(t *torrent) {
const interval = 10 * time.Second
const timeout = 60 * time.Second
for {
select {
case <-time.After(interval):
select {
case t.notifyErrorCommandC <- notifyErrorCommand{errCC: make(chan chan error, 1)}:
case <-t.closeC:
return
case <-time.After(timeout):
crash(t.id, "Torrent does not respond.")
}
case <-t.closeC:
return
case <-s.closeC:
return
}
}
}

func crash(torrentID string, msg string) {
f, err := ioutil.TempFile("", "rain-crash-dump-"+torrentID+"-*")
if err == nil {
msg += " Saving goroutine stacks to: " + f.Name()
b := make([]byte, 100*1024*1024)
n := runtime.Stack(b, true)
b = b[:n]
_, _ = f.Write(b)
_ = f.Close()
}
panic(msg)
}
34 changes: 0 additions & 34 deletions torrent/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"net/url"
"os"
"path/filepath"
"runtime"
"strconv"
"sync"
"time"
Expand Down Expand Up @@ -747,36 +746,3 @@ func (s *Session) StopAll() error {
}
return nil
}

// checkTorrent pings the torrent run loop periodically and crashes the program if a torrent does not respond in
// specified timeout. This is not a good behavior for a production program but it helps to find deadlocks easily,
// at least while developing.
func (s *Session) checkTorrent(t *torrent) {
const interval = 10 * time.Second
const timeout = 60 * time.Second
for {
select {
case <-time.After(interval):
select {
case t.notifyErrorCommandC <- notifyErrorCommand{errCC: make(chan chan error, 1)}:
case <-t.closeC:
return
case <-time.After(timeout):
crash("torrent does not responsd")
}
case <-t.closeC:
return
case <-s.closeC:
return
}
}
}

func crash(msg string) {
b := make([]byte, 100*1024*1024)
n := runtime.Stack(b, true)
b = b[:n]
os.Stderr.Write(b)
os.Stderr.WriteString("\n")
panic(msg)
}

0 comments on commit a064d3a

Please sign in to comment.