blob: 61445bc197b04833d0172168d1baeec7dc9d8ce8 (
plain)
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
|
//go:build linux
// +build linux
package servicereaper
import (
"os"
"os/signal"
"sync"
"syscall"
"github.com/sirupsen/logrus"
)
type service struct {
pidMap map[int]bool
mutex *sync.Mutex
}
var s = service{
pidMap: map[int]bool{},
mutex: &sync.Mutex{},
}
func AddPID(pid int) {
s.mutex.Lock()
s.pidMap[pid] = true
s.mutex.Unlock()
}
func Start() {
// create signal channel and only wait for SIGCHLD
sigc := make(chan os.Signal, 1)
signal.Notify(sigc, syscall.SIGCHLD)
// wait and reap in an extra goroutine
go reaper(sigc)
}
func reaper(sigc chan os.Signal) {
for {
// block until we receive SIGCHLD
<-sigc
s.mutex.Lock()
for pid := range s.pidMap {
var status syscall.WaitStatus
waitpid, err := syscall.Wait4(pid, &status, syscall.WNOHANG, nil)
if err != nil {
// do not log error for ECHILD
if err != syscall.ECHILD {
logrus.Warnf("Wait for pid %d failed: %v ", pid, err)
}
delete(s.pidMap, pid)
continue
}
// if pid == 0 nothing happened
if waitpid == 0 {
continue
}
if status.Exited() {
delete(s.pidMap, pid)
}
}
s.mutex.Unlock()
}
}
|