feat: add force kill signal handler that dumps stacks

This commit is contained in:
Gareth
2024-05-05 02:28:45 -07:00
parent be0cdd59be
commit 386f46a090
4 changed files with 26 additions and 9 deletions

View File

@@ -9,8 +9,10 @@ import (
"os" "os"
"os/signal" "os/signal"
"path" "path"
"runtime"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"syscall" "syscall"
"github.com/garethgeorge/backrest/gen/go/v1/v1connect" "github.com/garethgeorge/backrest/gen/go/v1/v1connect"
@@ -46,7 +48,8 @@ func main() {
} }
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
go onterm(cancel) go onterm(os.Interrupt, cancel)
go onterm(os.Interrupt, newForceKillHandler())
// Load the configuration // Load the configuration
configStore := createConfigProvider() configStore := createConfigProvider()
@@ -146,11 +149,13 @@ func createConfigProvider() config.ConfigStore {
} }
} }
func onterm(callback func()) { func onterm(s os.Signal, callback func()) {
sigchan := make(chan os.Signal, 1) sigchan := make(chan os.Signal, 1)
signal.Notify(sigchan, os.Interrupt, syscall.SIGTERM) signal.Notify(sigchan, s, syscall.SIGTERM)
for {
<-sigchan <-sigchan
callback() callback()
}
} }
func getSecret() []byte { func getSecret() []byte {
@@ -174,3 +179,17 @@ func getSecret() []byte {
} }
return secret return secret
} }
func newForceKillHandler() func() {
var times atomic.Int32
return func() {
if times.Load() > 0 {
buf := make([]byte, 1<<16)
runtime.Stack(buf, true)
os.Stderr.Write(buf)
zap.S().Fatal("dumped all running coroutine stack traces, forcing termination")
}
times.Add(1)
zap.S().Warn("attempting graceful shutdown, to force termination press Ctrl+C again")
}
}

View File

@@ -37,7 +37,7 @@ func NewRepoOrchestrator(config *v1.Config, repoConfig *v1.Repo, resticPath stri
var opts []restic.GenericOption var opts []restic.GenericOption
opts = append(opts, restic.WithEnviron()) opts = append(opts, restic.WithEnviron())
opts = append(opts, restic.WithEnv("RESTIC_PROGRESS_FPS=0.5")) opts = append(opts, restic.WithEnv("RESTIC_PROGRESS_FPS=2"))
if env := repoConfig.GetEnv(); len(env) != 0 { if env := repoConfig.GetEnv(); len(env) != 0 {
for _, e := range env { for _, e := range env {

View File

@@ -146,7 +146,7 @@ func (t *BackupTask) Run(ctx context.Context, st ScheduledTask, runner TaskRunne
zap.S().Warnf("unexpected message type %q in backup progress entry", entry.MessageType) zap.S().Warnf("unexpected message type %q in backup progress entry", entry.MessageType)
} }
if time.Since(lastSent) < 1*time.Second { if time.Since(lastSent) <= 1000*time.Millisecond {
return return
} }
lastSent = time.Now() lastSent = time.Now()

View File

@@ -50,8 +50,6 @@ func indexSnapshotsHelper(ctx context.Context, st ScheduledTask, taskRunner Task
t := st.Task t := st.Task
oplog := taskRunner.OpLog() oplog := taskRunner.OpLog()
config := taskRunner.Config()
repo, err := taskRunner.GetRepoOrchestrator(t.RepoID()) repo, err := taskRunner.GetRepoOrchestrator(t.RepoID())
if err != nil { if err != nil {
return fmt.Errorf("couldn't get repo %q: %w", t.RepoID(), err) return fmt.Errorf("couldn't get repo %q: %w", t.RepoID(), err)