diff --git a/pkg/cmd/infra/router/template.go b/pkg/cmd/infra/router/template.go index 28330db7c..ed9922410 100644 --- a/pkg/cmd/infra/router/template.go +++ b/pkg/cmd/infra/router/template.go @@ -539,7 +539,7 @@ func (o *TemplateRouterOptions) Run(stopCh <-chan struct{}) error { c.Run() } - proc.StartReaper() + proc.StartReaper(6 * time.Second) select { case <-stopCh: diff --git a/vendor/github.com/openshift/library-go/pkg/proc/reaper_unsupported.go b/vendor/github.com/openshift/library-go/pkg/proc/proc.go similarity index 76% rename from vendor/github.com/openshift/library-go/pkg/proc/reaper_unsupported.go rename to vendor/github.com/openshift/library-go/pkg/proc/proc.go index 75644fa5a..c9491af29 100644 --- a/vendor/github.com/openshift/library-go/pkg/proc/reaper_unsupported.go +++ b/vendor/github.com/openshift/library-go/pkg/proc/proc.go @@ -4,5 +4,5 @@ package proc // StartReaper has no effect on non-linux platforms. // Support for other unices will be added. -func StartReaper() { +func StartReaper(period time.Duration) { } diff --git a/vendor/github.com/openshift/library-go/pkg/proc/proc_linux.go b/vendor/github.com/openshift/library-go/pkg/proc/proc_linux.go new file mode 100644 index 000000000..76b923990 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/proc/proc_linux.go @@ -0,0 +1,78 @@ +package proc + +import ( + "bufio" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" + "syscall" + "time" + + "k8s.io/klog" +) + +// parseProcForZombies parses the current procfs mounted at /proc +// to find processes in the zombie state. +func parseProcForZombies() ([]int, error) { + files, err := ioutil.ReadDir("/proc") + if err != nil { + return nil, err + } + + var zombies []int + for _, file := range files { + processID, err := strconv.Atoi(file.Name()) + if err != nil { + break + } + stateFilePath := filepath.Join("/proc", file.Name(), "status") + fd, err := os.Open(stateFilePath) + if err != nil { + klog.V(4).Infof("Failed to open %q: %v", stateFilePath, err) + continue + } + defer fd.Close() + fs := bufio.NewScanner(fd) + for fs.Scan() { + line := fs.Text() + if strings.HasPrefix(line, "State:") { + if strings.Contains(line, "zombie") { + zombies = append(zombies, processID) + } + break + } + } + } + + return zombies, nil +} + +// StartReaper starts a goroutine to reap processes periodically if called +// from a pid 1 process. +func StartReaper(period time.Duration) { + if os.Getpid() == 1 { + go func() { + var zs []int + var err error + for { + zs, err = parseProcForZombies() + if err != nil { + klog.V(4).Infof(err.Error()) + continue + } + time.Sleep(period) + for _, z := range zs { + klog.V(4).Infof("Reaping zombie: %d", z) + cpid, err := syscall.Wait4(z, nil, syscall.WNOHANG, nil) + if err != nil { + klog.V(4).Infof("Zombie reap error: %v", err) + } else { + klog.V(4).Infof("Zombie reaped: %d", cpid) + } + } + } + }() + } +} diff --git a/vendor/github.com/openshift/library-go/pkg/proc/reaper.go b/vendor/github.com/openshift/library-go/pkg/proc/reaper.go deleted file mode 100644 index 21f5f71ff..000000000 --- a/vendor/github.com/openshift/library-go/pkg/proc/reaper.go +++ /dev/null @@ -1,37 +0,0 @@ -// +build linux - -package proc - -import ( - "os" - "os/signal" - "syscall" - - "k8s.io/klog" -) - -// StartReaper starts a goroutine to reap processes if called from a process -// that has pid 1. -func StartReaper() { - if os.Getpid() == 1 { - klog.V(4).Infof("Launching reaper") - go func() { - sigs := make(chan os.Signal, 1) - signal.Notify(sigs, syscall.SIGCHLD) - for { - // Wait for a child to terminate - sig := <-sigs - klog.V(4).Infof("Signal received: %v", sig) - for { - // Reap processes - cpid, _ := syscall.Wait4(-1, nil, syscall.WNOHANG, nil) - if cpid < 1 { - break - } - - klog.V(4).Infof("Reaped process with pid %d", cpid) - } - } - }() - } -}