-
Notifications
You must be signed in to change notification settings - Fork 0
/
signal.go
110 lines (99 loc) · 2.12 KB
/
signal.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package binit
import (
"log"
"os"
"os/exec"
"os/signal"
"strconv"
"strings"
"syscall"
"golang.org/x/sys/unix"
)
type Signaller struct {
signals *chan os.Signal
skipSignalLog []string
preStop string
preStopSignal []string
cmd *exec.Cmd
}
func NewSignaller(config Config) *Signaller {
signaller := &Signaller{
skipSignalLog: strings.Split(config.SKIP_SIGNAL_LOG, ","),
preStop: config.PRE_STOP,
preStopSignal: strings.Split(config.PRE_STOP_SIGNAL, ","),
}
return signaller
}
func (s *Signaller) Start(cmd *exec.Cmd) {
s.cmd = cmd
signals := make(chan os.Signal, 1)
s.signals = &signals
signal.Notify(*s.signals)
go s.Forward()
}
func (s *Signaller) logSignal(name string) bool {
if s == nil {
return true
}
for _, s := range s.skipSignalLog {
if s == name {
return false
}
}
return true
}
func (s *Signaller) isPreStopSingal(name string) bool {
if s == nil {
return false
}
for _, s := range s.preStopSignal {
if s == name {
return true
}
}
return false
}
func (s *Signaller) Forward() {
for signal := range *s.signals {
if signal == syscall.SIGCHLD {
continue
}
process := s.cmd.Process
pid := -1
if process != nil {
pid = process.Pid
}
sig := signal.(syscall.Signal)
sigName := unix.SignalName(sig)
preStopping := s.isPreStopSingal(sigName)
if preStopping {
log.Printf(
"received PRE_STOP_SIGNAL %s (=%d) for supervised process group of pid %d (%s) now",
sigName, sig, pid, s.cmd.Path,
)
if s.preStop != "" {
log.Printf("Executing PRE_STOP command for pid %d (%s) now", pid, s.cmd.Path)
waiter := NewWaiter()
env := map[string]string{}
if pid > 0 {
env["BINIT_CMD_PID"] = strconv.Itoa(pid)
}
runCommandWithEnv(s.preStop, waiter, &env)
} else {
log.Printf("PRE_STOP command is empty, so nothing will be executed")
}
} else {
if s.logSignal(sigName) {
log.Printf(
"Forwarding signal %s (=%d) to process group of pid %d (%s) now",
sigName, sig, pid, s.cmd.Path,
)
}
}
syscall.Kill(-pid, sig)
}
}
func (s *Signaller) Shutdown() {
close(*s.signals)
signal.Reset()
}