github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/libcmdline/fork_windows.go (about) 1 // Copyright 2018 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 //go:build windows 5 // +build windows 6 7 package libcmdline 8 9 import ( 10 "os" 11 "syscall" 12 13 "github.com/keybase/client/go/logger" 14 ) 15 16 const flagCreateNewConsole = 0x00000010 17 18 // SpawnDetachedProcess spawns a background process and detech from the calling 19 // process. 20 func SpawnDetachedProcess( 21 cmd string, args []string, log logger.Logger) (pid int, err error) { 22 var files []uintptr 23 var devnull *os.File 24 25 defer func() { 26 if err != nil && devnull != nil { 27 devnull.Close() 28 } 29 }() 30 31 // Failing to open nul is non-fatal here. 32 devnull, err = os.OpenFile("nul", os.O_RDONLY, 0) 33 if err != nil { 34 log.Warning("Cannot open nul: %v", err) 35 // 0 is an invalid handle, but more importantly it will 36 // not be passed to DuplicateHandle by Go. This works 37 // with Go 1.6, but is hacky. This code path is taken 38 // only on systems that are broken to begin with... 39 files = append(files, 0, 0, 0) 40 } else { 41 nullfd := devnull.Fd() 42 files = append(files, nullfd, nullfd, nullfd) 43 } 44 45 // Create the process with its own console, so it 46 // can outlive the parent process's console. 47 attr := syscall.ProcAttr{ 48 Env: os.Environ(), 49 Files: files, 50 Sys: &syscall.SysProcAttr{ 51 HideWindow: true, 52 CreationFlags: flagCreateNewConsole, 53 }, 54 } 55 56 pid, _, err = syscall.StartProcess(cmd, args, &attr) 57 return pid, err 58 }