Consider this trivial Go program, which demonstrates the standard way to "fork off" a background process in Go. When it's run, it should immediately send itself to the background where it will write incrementing integers to output.txt once per second. It will keep running until you manually kill it.
This program works perfectly on Mac and Linux, but on Windows there is a weird behavior: it seems like it worked because I get a command prompt again immediately, and my process is indeed running in the background and writing those integers to output.txt. However, the background process gets killed when I close the terminal window.
The problem happens with both the standard cmd.exe, and the new fancy Windows Terminal that uses PowerShell. There is no such problem on Mac and Linux, where it quite properly survives terminal close, ssh logout, etc.
I tried using cmd.SysProcAttr to set syscall.CREATE_NEW_PROCESS_GROUP, but that made no difference.
My question is, what's causing it to die on Windows when the terminal is closed and how do I make it stop?
package main
import (
"fmt"
"os"
"os/exec"
"time"
)
var childEnv = "__IS_CHILD"
func main() {
if os.Getenv(childEnv) == "" {
fork()
os.Exit(0)
}
for i := 0; ; i++ {
fmt.Println(i)
time.Sleep(time.Second)
}
}
func fork() {
outfile, err := os.Create("output.txt")
if err != nil {
panic(err)
}
cmd := exec.Command(os.Args[0])
cmd.Env = append(os.Environ(), fmt.Sprintf("%v=%v", childEnv, 1))
cmd.Stdout = outfile
cmd.Stderr = outfile
if err = cmd.Start(); err != nil {
panic(err)
}
}