-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathreaper.go
71 lines (63 loc) · 1.77 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
// Copyright © 2016 Pennock Tech, LLC.
// All rights reserved, except as granted under license.
// Licensed per file LICENSE.txt
package main
import (
"os"
"os/signal"
"syscall"
"time"
"github.com/sirupsen/logrus"
)
// We expect to be the only process running inside a jail/container, so we
// should reap all children, always ... just in case we're not.
func childReaper(log logrus.FieldLogger) {
log = log.WithField("subsystem", "reaper")
// We don't assume signals do not coalesce; we might get a SIGCHLD, we
// might not. Instead, we just swallow all SIGCHLD and we wait.
// We wait including WUNTRACED so that if "something happens" with a child,
// we at least log it, and WCONTINUED too.
// If you see these in the logs and you have set up an isolated environment,
// it's intrusion spoor.
go func() {
ch := make(chan os.Signal, 20)
signal.Notify(ch, syscall.SIGCHLD)
for {
log.WithField("signal", <-ch).Info("signal received")
}
}()
var status syscall.WaitStatus
var rusage syscall.Rusage
for {
pid, err := syscall.Wait4(-1, &status, syscall.WUNTRACED|syscall.WCONTINUED, &rusage)
if err != nil {
switch err {
case syscall.EINTR:
continue
case syscall.ECHILD:
time.Sleep(time.Second)
continue
}
log.WithError(err).Info("error from Wait4()")
time.Sleep(250 * time.Millisecond)
continue
}
l := log.WithField("pid", pid)
if status.Exited() {
l = l.WithField("exit-code", status.ExitStatus())
}
if status.CoreDump() {
l = l.WithField("core-dumped", true)
}
if status.Signaled() {
l = l.WithField("died-signal", status.Signal())
}
if status.Stopped() {
l = l.WithField("stopped", status.StopSignal())
}
if status.Continued() {
l = l.WithField("continued", true)
}
l.Info("child state")
}
}