logging: added a log on panic
Since panics still regularly "destroy" the terminal, it is hard to get a stack trace for panics you do not anticipate. This commit adds a panic handler that automatically creates a logfile inside the current working directory. It has to be added to every goroutine that is started and will repair the terminal on a panic. Signed-off-by: Moritz Poldrack <git@moritz.sh> Acked-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
parent
feecc09b73
commit
ae83373fa6
27 changed files with 161 additions and 23 deletions
24
aerc.go
24
aerc.go
|
@ -7,7 +7,6 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"runtime/debug"
|
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -25,6 +24,7 @@ import (
|
||||||
"git.sr.ht/~rjarry/aerc/lib"
|
"git.sr.ht/~rjarry/aerc/lib"
|
||||||
"git.sr.ht/~rjarry/aerc/lib/templates"
|
"git.sr.ht/~rjarry/aerc/lib/templates"
|
||||||
libui "git.sr.ht/~rjarry/aerc/lib/ui"
|
libui "git.sr.ht/~rjarry/aerc/lib/ui"
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/widgets"
|
"git.sr.ht/~rjarry/aerc/widgets"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -112,6 +112,7 @@ func setWindowTitle() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
opts, optind, err := getopt.Getopts(os.Args, "v")
|
opts, optind, err := getopt.Getopts(os.Args, "v")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
|
@ -165,8 +166,6 @@ func main() {
|
||||||
ui *libui.UI
|
ui *libui.UI
|
||||||
)
|
)
|
||||||
|
|
||||||
defer PanicTermFix(ui) // recover upon panic and try restoring the pty
|
|
||||||
|
|
||||||
aerc = widgets.NewAerc(conf, logger, func(cmd []string) error {
|
aerc = widgets.NewAerc(conf, logger, func(cmd []string) error {
|
||||||
return execCommand(aerc, ui, cmd)
|
return execCommand(aerc, ui, cmd)
|
||||||
}, func(cmd string) []string {
|
}, func(cmd string) []string {
|
||||||
|
@ -178,6 +177,9 @@ func main() {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
defer ui.Close()
|
defer ui.Close()
|
||||||
|
logging.UICleanup = func() {
|
||||||
|
ui.Close()
|
||||||
|
}
|
||||||
|
|
||||||
if conf.Ui.MouseEnabled {
|
if conf.Ui.MouseEnabled {
|
||||||
ui.EnableMouse()
|
ui.EnableMouse()
|
||||||
|
@ -225,19 +227,3 @@ func main() {
|
||||||
}
|
}
|
||||||
aerc.CloseBackends()
|
aerc.CloseBackends()
|
||||||
}
|
}
|
||||||
|
|
||||||
//FatalTermFix prints the stacktrace upon panic and tries to recover the term
|
|
||||||
// not doing that leaves the terminal in a broken state
|
|
||||||
func PanicTermFix(ui *libui.UI) {
|
|
||||||
var err interface{}
|
|
||||||
if err = recover(); err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
debug.PrintStack()
|
|
||||||
if ui != nil {
|
|
||||||
ui.Close()
|
|
||||||
}
|
|
||||||
fmt.Fprintf(os.Stderr, "aerc crashed: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/models"
|
"git.sr.ht/~rjarry/aerc/models"
|
||||||
"git.sr.ht/~rjarry/aerc/widgets"
|
"git.sr.ht/~rjarry/aerc/widgets"
|
||||||
"git.sr.ht/~sircmpwn/getopt"
|
"git.sr.ht/~sircmpwn/getopt"
|
||||||
|
@ -52,7 +53,11 @@ func (Compose) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
}
|
}
|
||||||
tab.Content.Invalidate()
|
tab.Content.Invalidate()
|
||||||
})
|
})
|
||||||
go composer.AppendContents(strings.NewReader(body))
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
|
composer.AppendContents(strings.NewReader(body))
|
||||||
|
}()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"git.sr.ht/~rjarry/aerc/commands"
|
"git.sr.ht/~rjarry/aerc/commands"
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/models"
|
"git.sr.ht/~rjarry/aerc/models"
|
||||||
"git.sr.ht/~rjarry/aerc/widgets"
|
"git.sr.ht/~rjarry/aerc/widgets"
|
||||||
"git.sr.ht/~sircmpwn/getopt"
|
"git.sr.ht/~sircmpwn/getopt"
|
||||||
|
@ -111,7 +112,11 @@ func (Recover) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
tab.Name = subject
|
tab.Name = subject
|
||||||
tab.Content.Invalidate()
|
tab.Content.Invalidate()
|
||||||
})
|
})
|
||||||
go composer.AppendContents(bytes.NewReader(data))
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
|
composer.AppendContents(bytes.NewReader(data))
|
||||||
|
}()
|
||||||
|
|
||||||
// remove file if force flag is set
|
// remove file if force flag is set
|
||||||
if force {
|
if force {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/miolini/datacounter"
|
"github.com/miolini/datacounter"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/models"
|
"git.sr.ht/~rjarry/aerc/models"
|
||||||
"git.sr.ht/~rjarry/aerc/widgets"
|
"git.sr.ht/~rjarry/aerc/widgets"
|
||||||
"git.sr.ht/~rjarry/aerc/worker/types"
|
"git.sr.ht/~rjarry/aerc/worker/types"
|
||||||
|
@ -66,6 +67,8 @@ func (Postpone) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
// run this as a goroutine so we can make other progress. The message
|
// run this as a goroutine so we can make other progress. The message
|
||||||
// will be saved once the directory is created.
|
// will be saved once the directory is created.
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
errStr := <-errChan
|
errStr := <-errChan
|
||||||
if errStr != "" {
|
if errStr != "" {
|
||||||
aerc.PushError(errStr)
|
aerc.PushError(errStr)
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"git.sr.ht/~rjarry/aerc/lib"
|
"git.sr.ht/~rjarry/aerc/lib"
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/models"
|
"git.sr.ht/~rjarry/aerc/models"
|
||||||
"git.sr.ht/~rjarry/aerc/widgets"
|
"git.sr.ht/~rjarry/aerc/widgets"
|
||||||
"git.sr.ht/~rjarry/aerc/worker/types"
|
"git.sr.ht/~rjarry/aerc/worker/types"
|
||||||
|
@ -100,6 +101,8 @@ func (Send) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
failCh := make(chan error)
|
failCh := make(chan error)
|
||||||
//writer
|
//writer
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
var sender io.WriteCloser
|
var sender io.WriteCloser
|
||||||
switch ctx.scheme {
|
switch ctx.scheme {
|
||||||
case "smtp":
|
case "smtp":
|
||||||
|
@ -131,6 +134,8 @@ func (Send) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
|
|
||||||
//cleanup + copy to sent
|
//cleanup + copy to sent
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
err = <-failCh
|
err = <-failCh
|
||||||
if err != nil {
|
if err != nil {
|
||||||
aerc.PushError(strings.ReplaceAll(err.Error(), "\n", " "))
|
aerc.PushError(strings.ReplaceAll(err.Error(), "\n", " "))
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/widgets"
|
"git.sr.ht/~rjarry/aerc/widgets"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -45,6 +46,8 @@ func (ExecCmd) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
cmd.Env = env
|
cmd.Env = env
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
aerc.PushError(err.Error())
|
aerc.PushError(err.Error())
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.sr.ht/~rjarry/aerc/commands"
|
"git.sr.ht/~rjarry/aerc/commands"
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/models"
|
"git.sr.ht/~rjarry/aerc/models"
|
||||||
"git.sr.ht/~rjarry/aerc/widgets"
|
"git.sr.ht/~rjarry/aerc/widgets"
|
||||||
"git.sr.ht/~rjarry/aerc/worker/types"
|
"git.sr.ht/~rjarry/aerc/worker/types"
|
||||||
|
@ -94,6 +95,8 @@ func (Archive) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
}
|
}
|
||||||
// we need to do that in the background, else we block the main thread
|
// we need to do that in the background, else we block the main thread
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
if success {
|
if success {
|
||||||
aerc.PushStatus("Messages archived.", 10*time.Second)
|
aerc.PushStatus("Messages archived.", 10*time.Second)
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.sr.ht/~rjarry/aerc/commands"
|
"git.sr.ht/~rjarry/aerc/commands"
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/widgets"
|
"git.sr.ht/~rjarry/aerc/widgets"
|
||||||
"git.sr.ht/~rjarry/aerc/worker/types"
|
"git.sr.ht/~rjarry/aerc/worker/types"
|
||||||
|
|
||||||
|
@ -89,6 +90,8 @@ func (Pipe) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
defer pipe.Close()
|
defer pipe.Close()
|
||||||
io.Copy(pipe, reader)
|
io.Copy(pipe, reader)
|
||||||
}()
|
}()
|
||||||
|
@ -146,6 +149,8 @@ func (Pipe) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
})
|
})
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-done:
|
case <-done:
|
||||||
break
|
break
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"git.sr.ht/~sircmpwn/getopt"
|
"git.sr.ht/~sircmpwn/getopt"
|
||||||
|
|
||||||
"git.sr.ht/~rjarry/aerc/lib"
|
"git.sr.ht/~rjarry/aerc/lib"
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/models"
|
"git.sr.ht/~rjarry/aerc/models"
|
||||||
"git.sr.ht/~rjarry/aerc/widgets"
|
"git.sr.ht/~rjarry/aerc/widgets"
|
||||||
"git.sr.ht/~rjarry/aerc/worker/types"
|
"git.sr.ht/~rjarry/aerc/worker/types"
|
||||||
|
@ -169,6 +170,8 @@ func (FlagMsg) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
|
|
||||||
// We need to do flagging in the background, else we block the main thread
|
// We need to do flagging in the background, else we block the main thread
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
if success {
|
if success {
|
||||||
aerc.PushStatus(actionName+" flag '"+flagName+"' successful", 10*time.Second)
|
aerc.PushStatus(actionName+" flag '"+flagName+"' successful", 10*time.Second)
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.sr.ht/~rjarry/aerc/lib"
|
"git.sr.ht/~rjarry/aerc/lib"
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/widgets"
|
"git.sr.ht/~rjarry/aerc/widgets"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -66,6 +67,8 @@ func (Open) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
err := xdg.Wait()
|
err := xdg.Wait()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
aerc.PushError(err.Error())
|
aerc.PushError(err.Error())
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/mitchellh/go-homedir"
|
"github.com/mitchellh/go-homedir"
|
||||||
|
|
||||||
"git.sr.ht/~rjarry/aerc/commands"
|
"git.sr.ht/~rjarry/aerc/commands"
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/models"
|
"git.sr.ht/~rjarry/aerc/models"
|
||||||
"git.sr.ht/~rjarry/aerc/widgets"
|
"git.sr.ht/~rjarry/aerc/widgets"
|
||||||
)
|
)
|
||||||
|
@ -126,6 +127,8 @@ func (Save) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
|
|
||||||
// we need to wait for the callback prior to displaying a result
|
// we need to wait for the callback prior to displaying a result
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
err := <-ch
|
err := <-ch
|
||||||
if err != nil {
|
if err != nil {
|
||||||
aerc.PushError(fmt.Sprintf("Save failed: %v", err))
|
aerc.PushError(fmt.Sprintf("Save failed: %v", err))
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/lithammer/fuzzysearch/fuzzy"
|
"github.com/lithammer/fuzzysearch/fuzzy"
|
||||||
|
|
||||||
"git.sr.ht/~rjarry/aerc/lib"
|
"git.sr.ht/~rjarry/aerc/lib"
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/models"
|
"git.sr.ht/~rjarry/aerc/models"
|
||||||
"git.sr.ht/~rjarry/aerc/widgets"
|
"git.sr.ht/~rjarry/aerc/widgets"
|
||||||
"github.com/gdamore/tcell/v2"
|
"github.com/gdamore/tcell/v2"
|
||||||
|
@ -51,6 +52,8 @@ func QuickTerm(aerc *widgets.Aerc, args []string, stdin io.Reader) (*widgets.Ter
|
||||||
status := make(chan error, 1)
|
status := make(chan error, 1)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
_, err := io.Copy(pipe, stdin)
|
_, err := io.Copy(pipe, stdin)
|
||||||
defer pipe.Close()
|
defer pipe.Close()
|
||||||
status <- err
|
status <- err
|
||||||
|
|
|
@ -3,6 +3,8 @@ package lib
|
||||||
import (
|
import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
var openBin string = "xdg-open"
|
var openBin string = "xdg-open"
|
||||||
|
@ -49,6 +51,8 @@ func (xdg *xdgOpen) Start() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
xdg.errCh <- xdg.cmd.Wait()
|
xdg.errCh <- xdg.cmd.Wait()
|
||||||
close(xdg.errCh)
|
close(xdg.errCh)
|
||||||
}()
|
}()
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"github.com/kyoh86/xdg"
|
"github.com/kyoh86/xdg"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -36,6 +37,8 @@ func StartServer(logger *log.Logger) (*AercServer, error) {
|
||||||
}
|
}
|
||||||
// TODO: stash clients and close them on exit... bleh racey
|
// TODO: stash clients and close them on exit... bleh racey
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
conn, err := l.Accept()
|
conn, err := l.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -44,7 +47,11 @@ func StartServer(logger *log.Logger) (*AercServer, error) {
|
||||||
as.logger.Printf("Closing Unix server: %v", err)
|
as.logger.Printf("Closing Unix server: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
go as.handleClient(conn)
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
|
as.handleClient(conn)
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return as, nil
|
return as, nil
|
||||||
|
|
|
@ -3,6 +3,7 @@ package ui
|
||||||
import (
|
import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"github.com/gdamore/tcell/v2"
|
"github.com/gdamore/tcell/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -43,6 +44,8 @@ func Initialize(content DrawableInteractive) (*UI, error) {
|
||||||
|
|
||||||
state.exit.Store(false)
|
state.exit.Store(false)
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
for !state.ShouldExit() {
|
for !state.ShouldExit() {
|
||||||
state.tcEvents <- screen.PollEvent()
|
state.tcEvents <- screen.PollEvent()
|
||||||
}
|
}
|
||||||
|
|
56
logging/panic-logger.go
Normal file
56
logging/panic-logger.go
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
package logging
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"runtime/debug"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var UICleanup = func() {}
|
||||||
|
|
||||||
|
// PanicHandler tries to restore the terminal. A stack trace is written to
|
||||||
|
// aerc-crash.log and then passed on if a panic occurs.
|
||||||
|
func PanicHandler() {
|
||||||
|
r := recover()
|
||||||
|
|
||||||
|
if r == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
UICleanup()
|
||||||
|
|
||||||
|
filename := time.Now().Format("/tmp/aerc-crash-20060102-150405.log")
|
||||||
|
|
||||||
|
panicLog, err := os.OpenFile(filename, os.O_SYNC|os.O_APPEND|os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0o600)
|
||||||
|
if err != nil {
|
||||||
|
// we tried, not possible. bye
|
||||||
|
panic(r)
|
||||||
|
}
|
||||||
|
defer panicLog.Close()
|
||||||
|
|
||||||
|
outputs := io.MultiWriter(panicLog, os.Stderr)
|
||||||
|
|
||||||
|
// if any error happens here, we do not care.
|
||||||
|
fmt.Fprintln(panicLog, strings.Repeat("#", 80))
|
||||||
|
fmt.Fprint(panicLog, strings.Repeat(" ", 34))
|
||||||
|
fmt.Fprintln(panicLog, "PANIC CAUGHT!")
|
||||||
|
fmt.Fprint(panicLog, strings.Repeat(" ", 24))
|
||||||
|
fmt.Fprintln(panicLog, time.Now().Format("2006-01-02T15:04:05.000000-0700"))
|
||||||
|
fmt.Fprintln(panicLog, strings.Repeat("#", 80))
|
||||||
|
fmt.Fprintf(outputs, "%s\n", panicMessage)
|
||||||
|
fmt.Fprintf(panicLog, "Error: %v\n\n", r)
|
||||||
|
panicLog.Write(debug.Stack())
|
||||||
|
fmt.Fprintf(os.Stderr, "\nThis error was also written to: %s\n", filename)
|
||||||
|
panic(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
const panicMessage = `
|
||||||
|
aerc has encountered a critical error and has terminated. Please help us fixing
|
||||||
|
this by sending this log and the steps to reproduce the crash to:
|
||||||
|
~rjarry/aerc-devel@lists.sr.ht
|
||||||
|
|
||||||
|
Thank you
|
||||||
|
`
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"git.sr.ht/~rjarry/aerc/lib/sort"
|
"git.sr.ht/~rjarry/aerc/lib/sort"
|
||||||
"git.sr.ht/~rjarry/aerc/lib/statusline"
|
"git.sr.ht/~rjarry/aerc/lib/statusline"
|
||||||
"git.sr.ht/~rjarry/aerc/lib/ui"
|
"git.sr.ht/~rjarry/aerc/lib/ui"
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/models"
|
"git.sr.ht/~rjarry/aerc/models"
|
||||||
"git.sr.ht/~rjarry/aerc/worker"
|
"git.sr.ht/~rjarry/aerc/worker"
|
||||||
"git.sr.ht/~rjarry/aerc/worker/types"
|
"git.sr.ht/~rjarry/aerc/worker/types"
|
||||||
|
@ -86,7 +87,11 @@ func NewAccountView(aerc *Aerc, conf *config.AercConfig, acct *config.AccountCon
|
||||||
view.msglist = NewMessageList(conf, logger, aerc)
|
view.msglist = NewMessageList(conf, logger, aerc)
|
||||||
view.grid.AddChild(view.msglist).At(0, 1)
|
view.grid.AddChild(view.msglist).At(0, 1)
|
||||||
|
|
||||||
go worker.Backend.Run()
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
|
worker.Backend.Run()
|
||||||
|
}()
|
||||||
|
|
||||||
worker.PostAction(&types.Configure{Config: acct}, nil)
|
worker.PostAction(&types.Configure{Config: acct}, nil)
|
||||||
worker.PostAction(&types.Connect{}, nil)
|
worker.PostAction(&types.Connect{}, nil)
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"git.sr.ht/~rjarry/aerc/lib"
|
"git.sr.ht/~rjarry/aerc/lib"
|
||||||
libsort "git.sr.ht/~rjarry/aerc/lib/sort"
|
libsort "git.sr.ht/~rjarry/aerc/lib/sort"
|
||||||
"git.sr.ht/~rjarry/aerc/lib/ui"
|
"git.sr.ht/~rjarry/aerc/lib/ui"
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/models"
|
"git.sr.ht/~rjarry/aerc/models"
|
||||||
"git.sr.ht/~rjarry/aerc/worker/types"
|
"git.sr.ht/~rjarry/aerc/worker/types"
|
||||||
)
|
)
|
||||||
|
@ -128,6 +129,8 @@ func (dirlist *DirectoryList) Select(name string) {
|
||||||
dirlist.skipSelect = make(chan bool)
|
dirlist.skipSelect = make(chan bool)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-time.After(dirlist.UiConfig().DirListDelay):
|
case <-time.After(dirlist.UiConfig().DirListDelay):
|
||||||
dirlist.worker.PostAction(&types.OpenDirectory{Directory: name},
|
dirlist.worker.PostAction(&types.OpenDirectory{Directory: name},
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"git.sr.ht/~rjarry/aerc/lib"
|
"git.sr.ht/~rjarry/aerc/lib"
|
||||||
"git.sr.ht/~rjarry/aerc/lib/format"
|
"git.sr.ht/~rjarry/aerc/lib/format"
|
||||||
"git.sr.ht/~rjarry/aerc/lib/ui"
|
"git.sr.ht/~rjarry/aerc/lib/ui"
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/models"
|
"git.sr.ht/~rjarry/aerc/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -600,6 +601,8 @@ func (pv *PartViewer) attemptCopy() {
|
||||||
pv.copyFilterOutToPager() //delayed until we write to the sink
|
pv.copyFilterOutToPager() //delayed until we write to the sink
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
pv.writeMailHeaders()
|
pv.writeMailHeaders()
|
||||||
if strings.EqualFold(pv.part.MIMEType, "text") {
|
if strings.EqualFold(pv.part.MIMEType, "text") {
|
||||||
// if the content is plain we can strip ansi control chars
|
// if the content is plain we can strip ansi control chars
|
||||||
|
@ -645,6 +648,8 @@ func (pv *PartViewer) copyFilterOutToPager() {
|
||||||
pv.filter.Start()
|
pv.filter.Start()
|
||||||
ch := make(chan interface{})
|
ch := make(chan interface{})
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
_, err := io.Copy(pv.pagerin, stdout)
|
_, err := io.Copy(pv.pagerin, stdout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pv.err = err
|
pv.err = err
|
||||||
|
@ -654,6 +659,8 @@ func (pv *PartViewer) copyFilterOutToPager() {
|
||||||
ch <- nil
|
ch <- nil
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
_, err := io.Copy(pv.pagerin, stderr)
|
_, err := io.Copy(pv.pagerin, stderr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pv.err = err
|
pv.err = err
|
||||||
|
@ -663,6 +670,8 @@ func (pv *PartViewer) copyFilterOutToPager() {
|
||||||
ch <- nil
|
ch <- nil
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
<-ch
|
<-ch
|
||||||
<-ch
|
<-ch
|
||||||
pv.filter.Wait()
|
pv.filter.Wait()
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
"git.sr.ht/~rjarry/aerc/config"
|
"git.sr.ht/~rjarry/aerc/config"
|
||||||
"git.sr.ht/~rjarry/aerc/lib/ui"
|
"git.sr.ht/~rjarry/aerc/lib/ui"
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Spinner struct {
|
type Spinner struct {
|
||||||
|
@ -37,6 +38,8 @@ func (s *Spinner) Start() {
|
||||||
atomic.StoreInt64(&s.frame, 0)
|
atomic.StoreInt64(&s.frame, 0)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-s.stop:
|
case <-s.stop:
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"git.sr.ht/~rjarry/aerc/config"
|
"git.sr.ht/~rjarry/aerc/config"
|
||||||
"git.sr.ht/~rjarry/aerc/lib/ui"
|
"git.sr.ht/~rjarry/aerc/lib/ui"
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StatusLine struct {
|
type StatusLine struct {
|
||||||
|
@ -78,6 +79,8 @@ func (status *StatusLine) Push(text string, expiry time.Duration) *StatusMessage
|
||||||
}
|
}
|
||||||
status.stack = append(status.stack, msg)
|
status.stack = append(status.stack, msg)
|
||||||
go (func() {
|
go (func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
time.Sleep(expiry)
|
time.Sleep(expiry)
|
||||||
for i, m := range status.stack {
|
for i, m := range status.stack {
|
||||||
if m == msg {
|
if m == msg {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"git.sr.ht/~rjarry/aerc/lib/ui"
|
"git.sr.ht/~rjarry/aerc/lib/ui"
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
|
|
||||||
"github.com/creack/pty"
|
"github.com/creack/pty"
|
||||||
vterm "github.com/ddevault/go-libvterm"
|
vterm "github.com/ddevault/go-libvterm"
|
||||||
|
@ -124,6 +125,8 @@ func NewTerminal(cmd *exec.Cmd) (*Terminal, error) {
|
||||||
term.start = make(chan interface{})
|
term.start = make(chan interface{})
|
||||||
screen := term.vterm.ObtainScreen()
|
screen := term.vterm.ObtainScreen()
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
<-term.start
|
<-term.start
|
||||||
buf := make([]byte, 4096)
|
buf := make([]byte, 4096)
|
||||||
for {
|
for {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/emersion/go-message/mail"
|
"github.com/emersion/go-message/mail"
|
||||||
"github.com/emersion/go-message/textproto"
|
"github.com/emersion/go-message/textproto"
|
||||||
|
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/models"
|
"git.sr.ht/~rjarry/aerc/models"
|
||||||
"git.sr.ht/~rjarry/aerc/worker/types"
|
"git.sr.ht/~rjarry/aerc/worker/types"
|
||||||
)
|
)
|
||||||
|
@ -169,6 +170,8 @@ func (imapw *IMAPWorker) handleFetchMessages(
|
||||||
done := make(chan error)
|
done := make(chan error)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
var reterr error
|
var reterr error
|
||||||
for _msg := range messages {
|
for _msg := range messages {
|
||||||
imapw.seqMap[_msg.SeqNum-1] = _msg.Uid
|
imapw.seqMap[_msg.SeqNum-1] = _msg.Uid
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/emersion/go-imap"
|
"github.com/emersion/go-imap"
|
||||||
|
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/worker/types"
|
"git.sr.ht/~rjarry/aerc/worker/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -22,6 +23,8 @@ func (imapw *IMAPWorker) handleDeleteMessages(msg *types.DeleteMessages) {
|
||||||
ch := make(chan uint32)
|
ch := make(chan uint32)
|
||||||
done := make(chan interface{})
|
done := make(chan interface{})
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
for seqNum := range ch {
|
for seqNum := range ch {
|
||||||
i := seqNum - 1
|
i := seqNum - 1
|
||||||
deleted = append(deleted, imapw.seqMap[i])
|
deleted = append(deleted, imapw.seqMap[i])
|
||||||
|
|
|
@ -3,6 +3,7 @@ package imap
|
||||||
import (
|
import (
|
||||||
"github.com/emersion/go-imap"
|
"github.com/emersion/go-imap"
|
||||||
|
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/models"
|
"git.sr.ht/~rjarry/aerc/models"
|
||||||
"git.sr.ht/~rjarry/aerc/worker/types"
|
"git.sr.ht/~rjarry/aerc/worker/types"
|
||||||
)
|
)
|
||||||
|
@ -13,6 +14,8 @@ func (imapw *IMAPWorker) handleListDirectories(msg *types.ListDirectories) {
|
||||||
done := make(chan interface{})
|
done := make(chan interface{})
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
for mbox := range mailboxes {
|
for mbox := range mailboxes {
|
||||||
if !canOpen(mbox) {
|
if !canOpen(mbox) {
|
||||||
// no need to pass this to handlers if it can't be opened
|
// no need to pass this to handlers if it can't be opened
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
|
|
||||||
"git.sr.ht/~rjarry/aerc/lib"
|
"git.sr.ht/~rjarry/aerc/lib"
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/models"
|
"git.sr.ht/~rjarry/aerc/models"
|
||||||
"git.sr.ht/~rjarry/aerc/worker/handlers"
|
"git.sr.ht/~rjarry/aerc/worker/handlers"
|
||||||
"git.sr.ht/~rjarry/aerc/worker/types"
|
"git.sr.ht/~rjarry/aerc/worker/types"
|
||||||
|
@ -83,6 +84,8 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
|
||||||
if w.client != nil && w.client.State() == imap.SelectedState {
|
if w.client != nil && w.client.State() == imap.SelectedState {
|
||||||
w.idleStop = make(chan struct{})
|
w.idleStop = make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
w.idleDone <- w.client.Idle(w.idleStop, &client.IdleOptions{LogoutTimeout: 0, PollInterval: 0})
|
w.idleDone <- w.client.Idle(w.idleStop, &client.IdleOptions{LogoutTimeout: 0, PollInterval: 0})
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
|
|
||||||
"git.sr.ht/~rjarry/aerc/config"
|
"git.sr.ht/~rjarry/aerc/config"
|
||||||
"git.sr.ht/~rjarry/aerc/lib/uidstore"
|
"git.sr.ht/~rjarry/aerc/lib/uidstore"
|
||||||
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/models"
|
"git.sr.ht/~rjarry/aerc/models"
|
||||||
"git.sr.ht/~rjarry/aerc/worker/handlers"
|
"git.sr.ht/~rjarry/aerc/worker/handlers"
|
||||||
"git.sr.ht/~rjarry/aerc/worker/lib"
|
"git.sr.ht/~rjarry/aerc/worker/lib"
|
||||||
|
@ -180,6 +181,8 @@ func (w *worker) handleConnect(msg *types.Connect) error {
|
||||||
w.done(msg)
|
w.done(msg)
|
||||||
w.emitLabelList()
|
w.emitLabelList()
|
||||||
go func() {
|
go func() {
|
||||||
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
w.nmEvents <- &updateDirCounts{}
|
w.nmEvents <- &updateDirCounts{}
|
||||||
time.Sleep(backgroundRefreshDelay)
|
time.Sleep(backgroundRefreshDelay)
|
||||||
|
|
Loading…
Reference in a new issue