Golang:Child Processes成为Zombies

时间:2016-03-17 02:17:49

标签: go process stdout stdin zombie-process

我在Go中有一个应用程序重新路由二进制文件的STDIN和STDOUT,然后运行它们。简而言之,我在做:

- create command object with the binary path (lets call the object command A) - create command object with the binary path (calling it command B) - set the stdout of command B to the stdin of Command A - start command A - start command B

我注意到,当命令A运行时,只要命令B的进程退出,它就会变成进程表中的僵尸进程。

以下是一个例子:

commandA := exec.Command("samplebin")
commandB := exec.Command("sample2bin")

cmdAStdin := commandA.StdinPipe()

commandB.Stdout = cmdAStdin

commandA.Start()
commandB.Start()

如果commandB仍在运行时,如果它退出,为什么commandB会成为Zombie?我在Ubuntu 14上运行Go 1.5。

2 个答案:

答案 0 :(得分:15)

当进程退出时,无论其他进程正在运行, ALWAYS 都会变成僵尸。这就是流程终止的工作方式。该过程将保持僵尸状态,直到其父级调用wait以获得其退出状态,或通过忽略SIGCHLD(可能在孩子退出之前)表明它对孩子不感兴趣。它将保持僵尸,直到发生这种情况,以免退出状态丢失。

在您的示例中,您的进程(创建进程的进程)似乎是父进程,因此A和B都将保留为僵尸,直到您的进程收集它们为止。

如果一个进程在仍有子进程(运行或僵尸)时退出,那么这些子进程将被重定位到退出进程的父进程,这通常会忽略退出状态(清除僵尸)。

答案 1 :(得分:2)

同意退出进程成为僵尸的第一个答案,直到另一个进程等待进程。以下是我如何处理事情。

package main

import (
    "bytes"
    "io"
    "os"
    "os/exec"
)

func main() {
    c1 := exec.Command("samplebin")
    c2 := exec.Command("sample2bin")

    r, w := io.Pipe()
    c1.Stdout = w
    c2.Stdin = r

    var b2 bytes.Buffer
    c2.Stdout = &b2

    // Writing without a reader will deadlock so write in a goroutine
    go func() {
        // Close the writer or the pipe will not be closed for c2
        defer w.Close()
        defer c1.Wait()
        c1.Start()
    }()
    defer c2.Wait()
    c2.Start()
    io.Copy(os.Stdout, &b2)
}