...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package osutil
19
20 import (
21 "os"
22 "os/signal"
23 "sync"
24 "syscall"
25
26 "go.uber.org/zap"
27 )
28
29
30
31 type InterruptHandler func()
32
33 var (
34 interruptRegisterMu, interruptExitMu sync.Mutex
35
36
37 interruptHandlers = []InterruptHandler{}
38 )
39
40
41
42 func RegisterInterruptHandler(h InterruptHandler) {
43 interruptRegisterMu.Lock()
44 defer interruptRegisterMu.Unlock()
45 interruptHandlers = append(interruptHandlers, h)
46 }
47
48
49 func HandleInterrupts(lg *zap.Logger) {
50 notifier := make(chan os.Signal, 1)
51 signal.Notify(notifier, syscall.SIGINT, syscall.SIGTERM)
52
53 go func() {
54 sig := <-notifier
55
56 interruptRegisterMu.Lock()
57 ihs := make([]InterruptHandler, len(interruptHandlers))
58 copy(ihs, interruptHandlers)
59 interruptRegisterMu.Unlock()
60
61 interruptExitMu.Lock()
62
63 if lg != nil {
64 lg.Info("received signal; shutting down", zap.String("signal", sig.String()))
65 }
66
67 for _, h := range ihs {
68 h()
69 }
70 signal.Stop(notifier)
71 pid := syscall.Getpid()
72
73 if pid == 1 {
74 os.Exit(0)
75 }
76 setDflSignal(sig.(syscall.Signal))
77 syscall.Kill(pid, sig.(syscall.Signal))
78 }()
79 }
80
81
82 func Exit(code int) {
83 interruptExitMu.Lock()
84 os.Exit(code)
85 }
86
View as plain text