Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang: Child Processes become Zombies

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.

like image 801
Anfernee Avatar asked Mar 17 '16 02:03

Anfernee


People also ask

How do I fix zombie processes?

Additionally, you can also kill the zombie process by sending the SIGCHLD signal to the parent process to make the parent process exit cleanly with its zombie process.

What causes a zombie process?

A process in Unix or Unix-like operating systems becomes a zombie process when it has completed execution but one or some of its entries are still in the process table. If a process is ended by an "exit" call, all memory associated with it is reallocated to a new process; in this way, the system saves memory.

Is Orphan process different from a zombie process?

An orphan process is formed when it's parent dies while the process continues to execute, while zombie process is a process which has terminated but it's entry is there in the system.

How do you reap zombie processes?

The process of eliminating zombie processes is known as 'reaping'. The simplest method is to call wait , but this will block the parent process if the child has not yet terminated. Alternatives are to use waitpid to poll or SIGCHLD to reap asynchronously.


2 Answers

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

like image 91
Chris Dodd Avatar answered Oct 17 '22 22:10

Chris Dodd


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)
}
like image 3
WeakPointer Avatar answered Oct 17 '22 21:10

WeakPointer