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

1

There are 1 best solutions below

0
Sergey On

I figured it out. I just need to add the code below, then the detached process won't die when the terminal window is closed.

cmd.SysProcAttr = &syscall.SysProcAttr{
    CreationFlags: windows.CREATE_NEW_PROCESS_GROUP | windows.DETACHED_PROCESS,
}

There's documentation on Windows process creation flags here: https://learn.microsoft.com/en-us/windows/win32/procthread/process-creation-flags