Golang:子进程变成僵尸进程

huangapple go评论100阅读模式
英文:

Golang: Child Processes become Zombies

问题

我有一个使用Go编写的应用程序,它重新定向二进制文件的标准输入和标准输出,然后运行它们。简而言之,我正在做以下操作:

  • 使用二进制文件路径创建命令对象(我们称之为命令A)
  • 使用二进制文件路径创建命令对象(称之为命令B)
  • 将命令B的标准输出设置为命令A的标准输入
  • 启动命令A
  • 启动命令B

我注意到,每当命令B的进程在命令A仍在运行时退出时,它会成为进程表中的僵尸进程。

以下是一个示例:

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

cmdAStdin := commandA.StdinPipe()

commandB.Stdout = cmdAStdin

commandA.Start()
commandB.Start()

为什么在命令A仍在运行时,命令B退出后会成为僵尸进程?我在Ubuntu 14上运行的是Go 1.5版本。

英文:

I have an application in Go that reroutes the STDIN and STDOUT of binaries and then runs them. In a nutshell I'm doing:

`- 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
    `

I noticed whenever the process for command B exits while command A is running, it becomes a zombie process in the process table.

Here's an example:

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

cmdAStdin := commandA.StdinPipe()

commandB.Stdout = cmdAStdin

commandA.Start()
commandB.Start()

Why does commandB become a Zombie if it exits while commandA is still running? I'm running Go 1.5 on Ubuntu 14.

答案1

得分: 21

当一个进程退出时,无论其他进程是否在运行,它都会变成僵尸进程。这就是进程终止的方式。直到它的父进程调用wait来获取它的退出状态,或者通过忽略SIGCHLD信号表明它对子进程不感兴趣(这可能发生在子进程退出之前),该进程将保持为僵尸进程。在这之前,它将一直保持为僵尸进程,以免退出状态丢失。

在你的例子中,似乎你的进程(创建这些进程的进程)是父进程,所以A和B都会保持为僵尸进程,直到你的进程收集它们。

如果一个进程在仍然有子进程(无论是运行中的还是僵尸进程)的情况下退出,这些子进程将被重新分配给退出进程的父进程,后者通常会忽略退出状态(清理僵尸进程)。

英文:

When a process exits, it ALWAYS becomes a zombie, regardless of what other processes are running. That's just the way process termination works. The process will remain a zombie until its parent calls wait to get its exit status, or indicates that it is uninterested in children by ignoring SIGCHLD (which may have been before the child exited). It will remain a zombie until that happens, lest the exit status get lost.

In your example, it would seem that your process (the one creating the processes) is the parent, so both A and B will remain as zombies until your process collects them.

If a process exits while it still has children (either running or zombies), those children will be reparented to the exiting process's parent, which will generally ignore the exit status (clearing up the zombies).

答案2

得分: 3

同意第一个答案,即退出的进程会变成僵尸进程,直到被另一个进程等待。以下是我在Go语言中处理这种情况的方式。

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

    // 在没有读取器的情况下写入会导致死锁,因此在一个 goroutine 中进行写入
    go func() {
        // 关闭写入器,否则 c2 的管道将不会关闭
        defer w.Close()
        defer c1.Wait()
        c1.Start()
    }()
    defer c2.Wait()
    c2.Start()
    io.Copy(os.Stdout, &b2)
}

希望对你有帮助!

英文:

Agree with the first answer that exiting processes becomes zombies until the process is waited for by another process. Here's how I handle things in go.

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)
}

huangapple
  • 本文由 发表于 2016年3月17日 10:17:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/36050503.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定