From e83b21e373bcc44dcd54a9fc77c1f2788da3a960 Mon Sep 17 00:00:00 2001 From: mr c0b Date: Fri, 14 Jul 2017 14:23:20 -0700 Subject: [PATCH] loop reaping dead children Current code isn't very correct: because Linux signal system design follows SysV Unix behavior, when a SIGCHLD happens, it only means there are child programs died (either self-quit or involuntarily killed, from wstatus may figure out), linux kernel only deliver SIGCHLD once to parent before the parent process; so when SIGCHLD happens, you don't know is that one child only or more so the code need a loop until wait4 returns zero, at rumtime got this: ```console 2017/07/14 21:14:32 reap dead child: 579, wstatus: 0x00000000 2017/07/14 21:14:32 reap dead child: 580, wstatus: 0x00000000 2017/07/14 21:14:32 reap dead child: 583, wstatus: 0x00000000 ``` then in the container there are no more zombies. final resolve #26 --- sigchld_unix.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/sigchld_unix.go b/sigchld_unix.go index 65ed255..7d910a1 100644 --- a/sigchld_unix.go +++ b/sigchld_unix.go @@ -3,6 +3,7 @@ package main import ( + "log" "os" "os/signal" "syscall" @@ -23,6 +24,18 @@ func watchChildSignal() { } func reapChildren() { - var wstatus syscall.WaitStatus - syscall.Wait4(-1, &wstatus, syscall.WNOHANG, nil) + for { + var wstatus syscall.WaitStatus + wpid, err := syscall.Wait4(-1, &wstatus, syscall.WNOHANG, nil) + if err != nil { + log.Printf("syscall.Wait4 call failed: %v", err) + break + } + + if wpid != 0 { + log.Printf("reap dead child: %d, wstatus: %#08x", wpid, wstatus) + } else { + break + } + } }