This repository has been archived by the owner on Apr 5, 2020. It is now read-only.
forked from ayufan/gitlab-ci-multi-runner
/
reaper.go
93 lines (72 loc) · 2.12 KB
/
reaper.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
package reaper
/* Note: This is a *nix only implementation. */
// Prefer #include style directives.
import "fmt"
import "os"
import "os/signal"
import "syscall"
// Handle death of child (SIGCHLD) messages. Pushes the signal onto the
// notifications channel if there is a waiter.
func sigChildHandler(notifications chan os.Signal) {
var sigs = make(chan os.Signal, 3)
signal.Notify(sigs, syscall.SIGCHLD)
for {
var sig = <- sigs
select {
case notifications <-sig: /* published it. */
default:
/*
* Notifications channel full - drop it to the
* floor. This ensures we don't fill up the SIGCHLD
* queue. The reaper just waits for any child
* process (pid=-1), so we ain't loosing it!! ;^)
*/
}
}
} /* End of function sigChildHandler. */
// Be a good parent - clean up behind the children.
func reapChildren() {
var notifications = make(chan os.Signal, 1)
go sigChildHandler(notifications)
for {
var sig = <-notifications
fmt.Printf(" - Received signal %v\n", sig)
for {
var wstatus syscall.WaitStatus
/*
* Reap 'em, so that zombies don't accumulate.
* Plants vs. Zombies!!
*/
pid, err := syscall.Wait4(-1, &wstatus, 0, nil)
for syscall.EINTR == err {
pid, err = syscall.Wait4(-1, &wstatus, 0, nil)
}
if syscall.ECHILD == err {
break
}
fmt.Printf(" - Grim reaper cleanup: pid=%d, wstatus=%+v\n",
pid, wstatus)
}
}
} /* End of function reapChildren. */
/*
* ======================================================================
* Section: Exported functions
* ======================================================================
*/
// Entry point for the reaper code. Start reaping children in the
// background inside a goroutine.
func Reap() {
/*
* Only reap processes if we are taking over init's duties aka
* we are running as pid 1 inside a docker container.
*/
if 1 == os.Getpid() {
/*
* Ok, we are the grandma of 'em all, so we get to play
* the grim reaper.
* You will be missed, Terry Pratchett!! RIP
*/
go reapChildren()
}
} /* End of [exported] function Reap. */