github.com/yang-ricky/air@v1.30.0/runner/util_darwin.go (about) 1 package runner 2 3 import ( 4 "io" 5 "os" 6 "os/exec" 7 "syscall" 8 "time" 9 10 "github.com/pkg/errors" 11 ) 12 13 func (e *Engine) killCmd(cmd *exec.Cmd) (pid int, err error) { 14 pid = cmd.Process.Pid 15 pgid, err := syscall.Getpgid(cmd.Process.Pid) 16 if err != nil { 17 return pgid, errors.Wrapf(err, "failed to get pgid, pid %v", pid) 18 } 19 20 if e.config.Build.SendInterrupt { 21 // Sending a signal to make it clear to the process that it is time to turn off 22 if err = syscall.Kill(-pgid, syscall.SIGINT); err != nil { 23 e.mainDebug("trying to send signal failed %v", err) 24 return 25 } 26 time.Sleep(e.config.Build.KillDelay * time.Millisecond) 27 } 28 err = syscall.Kill(-pgid, syscall.SIGKILL) 29 if err != nil { 30 return pid, errors.Wrapf(err, "failed to kill process by pgid %v", pgid) 31 } 32 // Wait releases any resources associated with the Process. 33 _, err = cmd.Process.Wait() 34 if err != nil { 35 return pid, err 36 } 37 38 e.mainDebug("killed process pid %d successed", pid) 39 return pid, nil 40 } 41 42 func (e *Engine) startCmd(cmd string) (*exec.Cmd, io.WriteCloser, io.ReadCloser, io.ReadCloser, error) { 43 c := exec.Command("/bin/sh", "-c", cmd) 44 c.SysProcAttr = &syscall.SysProcAttr{ 45 Setpgid: true, 46 } 47 48 stderr, err := c.StderrPipe() 49 if err != nil { 50 return nil, nil, nil, nil, err 51 } 52 stdout, err := c.StdoutPipe() 53 if err != nil { 54 return nil, nil, nil, nil, err 55 } 56 stdin, err := c.StdinPipe() 57 if err != nil { 58 return nil, nil, nil, nil, err 59 } 60 61 c.Stdout = os.Stdout 62 c.Stderr = os.Stderr 63 64 err = c.Start() 65 if err != nil { 66 return nil, nil, nil, nil, err 67 } 68 return c, stdin, stdout, stderr, nil 69 }