I ran into this issue at work in a test runner we have that is written in Go and runs a test suite which is a node module, which itself spawns several subprocesses. The issue was that one of the subprocesses inherited its parents' stdout file descriptor, but would outlive the parent process being killed. If you use Go's
exec.Cmd to run a process and set its
Stderr to something that is not a
File, a goroutine will be spawned to drive that I/O when calling
Cmd.Start, and all such goroutines will be run to completion as part of
Cmd.Wait. In this situation, because the grandchild process stays alive, it keeps the stdout pipe open, thus
Cmd.Wait blocks until it exits.
subprocess.go is a minimal testcase to display the issue. It spawns itself as a child process with piped stdout, then waits one second before killing the subprocess and waiting on it. The child process spawns itself as a grandchild with inherited stdout and sleeps for 5 seconds before exiting. The grandchild process simply