1
1
mirror of https://github.com/walles/moar.git synced 2024-09-11 12:15:43 +03:00

Catch errors in goroutines and log them

This commit is contained in:
Johan Walles 2024-08-10 08:40:48 +02:00
parent 3b5b2ff31f
commit 6cf1223634
9 changed files with 77 additions and 5 deletions

View File

@ -322,6 +322,10 @@ func (p *Pager) StartPaging(screen twin.Screen, chromaStyle *chroma.Style, chrom
p.marks = make(map[rune]scrollPosition)
go func() {
defer func() {
panicHandler("StartPaging()/moreLinesAvailable", recover())
}()
for range p.reader.moreLinesAdded {
// Notify the main loop about the new lines so it can show them
screen.Events() <- eventMoreLinesAvailable{}
@ -337,6 +341,10 @@ func (p *Pager) StartPaging(screen twin.Screen, chromaStyle *chroma.Style, chrom
}()
go func() {
defer func() {
panicHandler("StartPaging()/spinner", recover())
}()
// Spin the spinner as long as contents is still loading
spinnerFrames := [...]string{"/.\\", "-o-", "\\O/", "| |"}
spinnerIndex := 0
@ -359,6 +367,10 @@ func (p *Pager) StartPaging(screen twin.Screen, chromaStyle *chroma.Style, chrom
}()
go func() {
defer func() {
panicHandler("StartPaging()/maybeDone", recover())
}()
for range p.reader.maybeDone {
screen.Events() <- eventMaybeDone{}
}

17
m/panicHandler.go Normal file
View File

@ -0,0 +1,17 @@
package m
// NOTE: This file should be identical to twin/panicHandler.go
import (
log "github.com/sirupsen/logrus"
)
func panicHandler(goroutineName string, recoverResult any) {
if recoverResult == nil {
return
}
log.WithFields(log.Fields{
"recoverResult": recoverResult,
}).Error("Goroutine panicked: " + goroutineName)
}

View File

@ -342,7 +342,7 @@ func NewReaderFromStream(name string, reader io.Reader, style chroma.Style, form
// then used for pre-allocating the lines slice, which improves large file
// loading performance.
//
// If lexer is not nil, the file will be highlighted after being fully read.
// If lexer is set, the file will be highlighted after being fully read.
//
// Note that you must call reader.SetStyleForHighlighting() after this to get
// highlighting.
@ -364,9 +364,13 @@ func newReaderFromStream(reader io.Reader, originalFileName *string, formatter c
done: &done,
}
// FIXME: Make sure that if we panic somewhere inside of this goroutine,
// the main program terminates and prints our panic stack trace.
go returnMe.readStream(reader, formatter, lexer)
go func() {
defer func() {
panicHandler("newReaderFromStream()/readStream()", recover())
}()
returnMe.readStream(reader, formatter, lexer)
}()
return &returnMe
}

View File

@ -124,6 +124,10 @@ func (p *Pager) findFirstHit(startPosition linenumbers.LineNumber, beforePositio
}
go func(i int, searchStart linenumbers.LineNumber, chunkBefore *linenumbers.LineNumber) {
defer func() {
panicHandler("findFirstHit()/chunkSearch", recover())
}()
findings[i] <- p._findFirstHit(searchStart, chunkBefore, backwards)
}(i, searchStart, chunkBefore)
}

17
twin/panicHandler.go Normal file
View File

@ -0,0 +1,17 @@
package twin
// NOTE: This file should be identical to m/panicHandler.go
import (
log "github.com/sirupsen/logrus"
)
func panicHandler(goroutineName string, recoverResult any) {
if recoverResult == nil {
return
}
log.WithFields(log.Fields{
"recoverResult": recoverResult,
}).Error("Goroutine panicked: " + goroutineName)
}

View File

@ -117,6 +117,10 @@ func (screen *UnixScreen) setupSigwinchNotification() {
sigwinch := make(chan os.Signal, 1)
signal.Notify(sigwinch, syscall.SIGWINCH)
go func() {
defer func() {
panicHandler("setupSigwinchNotification()/SIGWINCH", recover())
}()
for {
// Await window resize signal
<-sigwinch

View File

@ -31,6 +31,10 @@ func TestInterruptableReader_blockedOnReadImmediate(t *testing.T) {
}
readResultChan := make(chan readResult)
go func() {
defer func() {
panicHandler("TestInterruptableReader_blockedOnReadImmediate()", recover())
}()
buffer := make([]byte, 1)
n, err := testMe.Read(buffer)
readResultChan <- readResult{n, err}

View File

@ -179,7 +179,13 @@ func NewScreenWithMouseModeAndColorType(mouseMode MouseMode, terminalColorCount
screen.hideCursor(true)
go screen.mainLoop()
go func() {
defer func() {
panicHandler("NewScreenWithMouseModeAndColorType()/mainLoop()", recover())
}()
screen.mainLoop()
}()
return &screen, nil
}

View File

@ -269,6 +269,10 @@ func TestInterruptableReader_blockedOnRead(t *testing.T) {
}
readResultChan := make(chan readResult)
go func() {
defer func() {
panicHandler("TestInterruptableReader_blockedOnRead()", recover())
}()
buffer := make([]byte, 1)
n, err := testMe.Read(buffer)
readResultChan <- readResult{n, err}