github.com/mckael/restic@v0.8.3/cmd/restic/cleanup.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"os/signal"
     7  	"sync"
     8  	"syscall"
     9  
    10  	"github.com/restic/restic/internal/debug"
    11  )
    12  
    13  var cleanupHandlers struct {
    14  	sync.Mutex
    15  	list []func() error
    16  	done bool
    17  	ch   chan os.Signal
    18  }
    19  
    20  var stderr = os.Stderr
    21  
    22  func init() {
    23  	cleanupHandlers.ch = make(chan os.Signal)
    24  	go CleanupHandler(cleanupHandlers.ch)
    25  	signal.Notify(cleanupHandlers.ch, syscall.SIGINT)
    26  }
    27  
    28  // AddCleanupHandler adds the function f to the list of cleanup handlers so
    29  // that it is executed when all the cleanup handlers are run, e.g. when SIGINT
    30  // is received.
    31  func AddCleanupHandler(f func() error) {
    32  	cleanupHandlers.Lock()
    33  	defer cleanupHandlers.Unlock()
    34  
    35  	// reset the done flag for integration tests
    36  	cleanupHandlers.done = false
    37  
    38  	cleanupHandlers.list = append(cleanupHandlers.list, f)
    39  }
    40  
    41  // RunCleanupHandlers runs all registered cleanup handlers
    42  func RunCleanupHandlers() {
    43  	cleanupHandlers.Lock()
    44  	defer cleanupHandlers.Unlock()
    45  
    46  	if cleanupHandlers.done {
    47  		return
    48  	}
    49  	cleanupHandlers.done = true
    50  
    51  	for _, f := range cleanupHandlers.list {
    52  		err := f()
    53  		if err != nil {
    54  			fmt.Fprintf(stderr, "error in cleanup handler: %v\n", err)
    55  		}
    56  	}
    57  	cleanupHandlers.list = nil
    58  }
    59  
    60  // CleanupHandler handles the SIGINT signals.
    61  func CleanupHandler(c <-chan os.Signal) {
    62  	for s := range c {
    63  		debug.Log("signal %v received, cleaning up", s)
    64  		fmt.Fprintf(stderr, "%ssignal %v received, cleaning up\n", ClearLine(), s)
    65  
    66  		code := 0
    67  		if s != syscall.SIGINT {
    68  			code = 1
    69  		}
    70  
    71  		Exit(code)
    72  	}
    73  }
    74  
    75  // Exit runs the cleanup handlers and then terminates the process with the
    76  // given exit code.
    77  func Exit(code int) {
    78  	RunCleanupHandlers()
    79  	os.Exit(code)
    80  }