Recently I'm studying dumb-init and if I realized correctly it's trying to:
- runs as PID1, acting like a simple init system(reaping zombie processes)
- signal proxy/forwarding (which bash doesn't do)
In both here and here they all mentioned that bash
is capable of reaping zombie process so I'm trying to verify this but couldn't make it work.
First of all I wrote a simple Go program which spawn 10 zombie process:
func main() {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGKILL)
go func() {
for i := 0; i < 10; i++ {
sleepCmd := exec.Command("sleep", "1")
_ = sleepCmd.Start()
}
}()
fmt.Println("awaiting signal")
sig := <-sigs
fmt.Println()
fmt.Printf("received %s, exiting\n", sig.String())
}
build a image for it:
FROM golang:1.15-alpine3.12 as builder
WORKDIR /
COPY . .
RUN go build -o main main.go
FROM alpine:3.12
RUN apk --no-cache --update add dumb-init bash
WORKDIR /
COPY --from=builder /main /
COPY --from=builder /entrypoint.sh /
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/main"]
and if I run docker run -d <image>
it works as expected I can see 10 zombies process in ps
:
vagrant@vagrant:/vagrant/dumb-init$ ps aux | grep sleep
root 4388 0.0 0.0 0 0 ? Z 13:54 0:00 [sleep] <defunct>
root 4389 0.0 0.0 0 0 ? Z 13:54 0:00 [sleep] <defunct>
root 4390 0.0 0.0 0 0 ? Z 13:54 0:00 [sleep] <defunct>
root 4391 0.0 0.0 0 0 ? Z 13:54 0:00 [sleep] <defunct>
root 4392 0.0 0.0 0 0 ? Z 13:54 0:00 [sleep] <defunct>
root 4393 0.0 0.0 0 0 ? Z 13:54 0:00 [sleep] <defunct>
root 4394 0.0 0.0 0 0 ? Z 13:54 0:00 [sleep] <defunct>
root 4395 0.0 0.0 0 0 ? Z 13:54 0:00 [sleep] <defunct>
root 4396 0.0 0.0 0 0 ? Z 13:54 0:00 [sleep] <defunct>
root 4397 0.0 0.0 0 0 ? Z 13:54 0:00 [sleep] <defunct>
the 2nd step is to verify bash
is actually capable of reaping process, so I update my docker image ENTRYPOINT to entrypoint.sh, which just wrap my program with bash:
#!/bin/bash
/clever
if I run ps
in the container the zombie processes are still hanging there:
/ # ps
PID USER TIME COMMAND
1 root 0:00 {entrypoint.sh} /bin/bash /entrypoint.sh
7 root 0:00 /clever
13 root 0:00 [sleep]
14 root 0:00 [sleep]
15 root 0:00 [sleep]
16 root 0:00 [sleep]
17 root 0:00 [sleep]
18 root 0:00 [sleep]
19 root 0:00 [sleep]
20 root 0:00 [sleep]
21 root 0:00 [sleep]
22 root 0:00 [sleep]
31 root 0:00 /bin/sh
39 root 0:00 ps
Tried a few other way but still couldn't figure out how to reap the zombie process correctly.
thanks for the help.
ps
listing, the launching process is still running (pid 7) and I expect that to be the parent of thesleep
processes (pid 13, 14, ...), which would mean that thebash
root process (pid 1) won't reap them. – Catheterizewait
for the child and ignore theSIGCHLD
. Once you kill the parent, the zombie processes will be moved to PID 1 as a new parent. – Alimentation