From d768c1c3e463cac7e79a78253230026a95a32170 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Fri, 26 Aug 2022 23:04:59 +0200 Subject: [PATCH] Allow cleanup handlers to filter the exit code --- cmd/restic/cleanup.go | 14 ++++++++------ cmd/restic/cmd_check.go | 4 ++-- cmd/restic/cmd_mount.go | 4 ++-- cmd/restic/global.go | 10 +++++----- cmd/restic/global_debug.go | 4 ++-- cmd/restic/lock.go | 6 +++--- 6 files changed, 22 insertions(+), 20 deletions(-) diff --git a/cmd/restic/cleanup.go b/cmd/restic/cleanup.go index 67a007d59..61af72802 100644 --- a/cmd/restic/cleanup.go +++ b/cmd/restic/cleanup.go @@ -11,7 +11,7 @@ import ( var cleanupHandlers struct { sync.Mutex - list []func() error + list []func(code int) (int, error) done bool ch chan os.Signal } @@ -25,7 +25,7 @@ func init() { // AddCleanupHandler adds the function f to the list of cleanup handlers so // that it is executed when all the cleanup handlers are run, e.g. when SIGINT // is received. -func AddCleanupHandler(f func() error) { +func AddCleanupHandler(f func(code int) (int, error)) { cleanupHandlers.Lock() defer cleanupHandlers.Unlock() @@ -36,22 +36,24 @@ func AddCleanupHandler(f func() error) { } // RunCleanupHandlers runs all registered cleanup handlers -func RunCleanupHandlers() { +func RunCleanupHandlers(code int) int { cleanupHandlers.Lock() defer cleanupHandlers.Unlock() if cleanupHandlers.done { - return + return code } cleanupHandlers.done = true for _, f := range cleanupHandlers.list { - err := f() + var err error + code, err = f(code) if err != nil { Warnf("error in cleanup handler: %v\n", err) } } cleanupHandlers.list = nil + return code } // CleanupHandler handles the SIGINT signals. @@ -75,6 +77,6 @@ func CleanupHandler(c <-chan os.Signal) { // Exit runs the cleanup handlers and then terminates the process with the // given exit code. func Exit(code int) { - RunCleanupHandlers() + code = RunCleanupHandlers(code) os.Exit(code) } diff --git a/cmd/restic/cmd_check.go b/cmd/restic/cmd_check.go index 80b92862d..ab871e645 100644 --- a/cmd/restic/cmd_check.go +++ b/cmd/restic/cmd_check.go @@ -197,9 +197,9 @@ func runCheck(opts CheckOptions, gopts GlobalOptions, args []string) error { } cleanup := prepareCheckCache(opts, &gopts) - AddCleanupHandler(func() error { + AddCleanupHandler(func(code int) (int, error) { cleanup() - return nil + return code, nil }) repo, err := OpenRepository(gopts) diff --git a/cmd/restic/cmd_mount.go b/cmd/restic/cmd_mount.go index 747316f9f..2cc5bbdba 100644 --- a/cmd/restic/cmd_mount.go +++ b/cmd/restic/cmd_mount.go @@ -158,13 +158,13 @@ func runMount(opts MountOptions, gopts GlobalOptions, args []string) error { } } - AddCleanupHandler(func() error { + AddCleanupHandler(func(code int) (int, error) { debug.Log("running umount cleanup handler for mount at %v", mountpoint) err := umount(mountpoint) if err != nil { Warnf("unable to umount (maybe already umounted or still in use?): %v\n", err) } - return nil + return code, nil }) c, err := systemFuse.Mount(mountpoint, mountOptions...) diff --git a/cmd/restic/global.go b/cmd/restic/global.go index 3fe124dac..16afd993c 100644 --- a/cmd/restic/global.go +++ b/cmd/restic/global.go @@ -97,11 +97,11 @@ var isReadingPassword bool func init() { var cancel context.CancelFunc globalOptions.ctx, cancel = context.WithCancel(context.Background()) - AddCleanupHandler(func() error { + AddCleanupHandler(func(code int) (int, error) { // Must be called before the unlock cleanup handler to ensure that the latter is // not blocked due to limited number of backend connections, see #1434 cancel() - return nil + return code, nil }) f := cmdRoot.PersistentFlags() @@ -199,20 +199,20 @@ func restoreTerminal() { return } - AddCleanupHandler(func() error { + AddCleanupHandler(func(code int) (int, error) { // Restoring the terminal configuration while restic runs in the // background, causes restic to get stopped on unix systems with // a SIGTTOU signal. Thus only restore the terminal settings if // they might have been modified, which is the case while reading // a password. if !isReadingPassword { - return nil + return code, nil } err := checkErrno(term.Restore(fd, state)) if err != nil { fmt.Fprintf(os.Stderr, "unable to restore terminal state: %v\n", err) } - return err + return code, err }) } diff --git a/cmd/restic/global_debug.go b/cmd/restic/global_debug.go index 172f3451b..b798074d1 100644 --- a/cmd/restic/global_debug.go +++ b/cmd/restic/global_debug.go @@ -84,9 +84,9 @@ func runDebug() error { } if prof != nil { - AddCleanupHandler(func() error { + AddCleanupHandler(func(code int) (int, error) { prof.Stop() - return nil + return code, nil }) } diff --git a/cmd/restic/lock.go b/cmd/restic/lock.go index 64f82cf52..89acb0aef 100644 --- a/cmd/restic/lock.go +++ b/cmd/restic/lock.go @@ -119,7 +119,7 @@ func unlockRepo(lock *restic.Lock) { debug.Log("unable to find lock %v in the global list of locks, ignoring", lock) } -func unlockAll() error { +func unlockAll(code int) (int, error) { globalLocks.Lock() defer globalLocks.Unlock() @@ -127,11 +127,11 @@ func unlockAll() error { for _, lock := range globalLocks.locks { if err := lock.Unlock(); err != nil { debug.Log("error while unlocking: %v", err) - return err + return code, err } debug.Log("successfully removed lock") } globalLocks.locks = globalLocks.locks[:0] - return nil + return code, nil }