github.com/connorvict/air@v0.0.0-20231005162537-279bf07db0d5/runner/util_unix.go (about) 1 //go:build unix && !linux 2 3 package runner 4 5 import ( 6 "io" 7 "os" 8 "os/exec" 9 "syscall" 10 "time" 11 ) 12 13 func (e *Engine) killCmd(cmd *exec.Cmd) (pid int, err error) { 14 pid = cmd.Process.Pid 15 16 if e.config.Build.SendInterrupt { 17 // Sending a signal to make it clear to the process that it is time to turn off 18 if err = syscall.Kill(-pid, syscall.SIGINT); err != nil { 19 return 20 } 21 time.Sleep(e.config.Build.KillDelay) 22 } 23 // https://stackoverflow.com/questions/22470193/why-wont-go-kill-a-child-process-correctly 24 err = syscall.Kill(-pid, syscall.SIGKILL) 25 // Wait releases any resources associated with the Process. 26 _, _ = cmd.Process.Wait() 27 return pid, err 28 } 29 30 func (e *Engine) startCmd(cmd string) (*exec.Cmd, io.ReadCloser, io.ReadCloser, error) { 31 c := exec.Command("/bin/sh", "-c", cmd) 32 // because using pty cannot have same pgid 33 c.SysProcAttr = &syscall.SysProcAttr{ 34 Setpgid: true, 35 } 36 37 stderr, err := c.StderrPipe() 38 if err != nil { 39 return nil, nil, nil, err 40 } 41 stdout, err := c.StdoutPipe() 42 if err != nil { 43 return nil, nil, nil, err 44 } 45 46 c.Stdout = os.Stdout 47 c.Stderr = os.Stderr 48 49 err = c.Start() 50 if err != nil { 51 return nil, nil, nil, err 52 } 53 return c, stdout, stderr, nil 54 }