github.com/epfl-dcsl/gotee@v0.0.0-20200909122901-014b35f5e5e9/src/os/exec_posix.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows 6 7 package os 8 9 import ( 10 "syscall" 11 ) 12 13 // The only signal values guaranteed to be present in the os package 14 // on all systems are Interrupt (send the process an interrupt) and 15 // Kill (force the process to exit). Interrupt is not implemented on 16 // Windows; using it with os.Process.Signal will return an error. 17 var ( 18 Interrupt Signal = syscall.SIGINT 19 Kill Signal = syscall.SIGKILL 20 ) 21 22 func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) { 23 // If there is no SysProcAttr (ie. no Chroot or changed 24 // UID/GID), double-check existence of the directory we want 25 // to chdir into. We can make the error clearer this way. 26 if attr != nil && attr.Sys == nil && attr.Dir != "" { 27 if _, err := Stat(attr.Dir); err != nil { 28 pe := err.(*PathError) 29 pe.Op = "chdir" 30 return nil, pe 31 } 32 } 33 34 sysattr := &syscall.ProcAttr{ 35 Dir: attr.Dir, 36 Env: attr.Env, 37 Sys: attr.Sys, 38 } 39 if sysattr.Env == nil { 40 sysattr.Env = Environ() 41 } 42 for _, f := range attr.Files { 43 sysattr.Files = append(sysattr.Files, f.Fd()) 44 } 45 46 pid, h, e := syscall.StartProcess(name, argv, sysattr) 47 if e != nil { 48 return nil, &PathError{"fork/exec", name, e} 49 } 50 return newProcess(pid, h), nil 51 } 52 53 func (p *Process) kill() error { 54 return p.Signal(Kill) 55 } 56 57 // ProcessState stores information about a process, as reported by Wait. 58 type ProcessState struct { 59 pid int // The process's id. 60 status syscall.WaitStatus // System-dependent status info. 61 rusage *syscall.Rusage 62 } 63 64 // Pid returns the process id of the exited process. 65 func (p *ProcessState) Pid() int { 66 return p.pid 67 } 68 69 func (p *ProcessState) exited() bool { 70 return p.status.Exited() 71 } 72 73 func (p *ProcessState) success() bool { 74 return p.status.ExitStatus() == 0 75 } 76 77 func (p *ProcessState) sys() interface{} { 78 return p.status 79 } 80 81 func (p *ProcessState) sysUsage() interface{} { 82 return p.rusage 83 } 84 85 func (p *ProcessState) String() string { 86 if p == nil { 87 return "<nil>" 88 } 89 status := p.Sys().(syscall.WaitStatus) 90 res := "" 91 switch { 92 case status.Exited(): 93 res = "exit status " + itoa(status.ExitStatus()) 94 case status.Signaled(): 95 res = "signal: " + status.Signal().String() 96 case status.Stopped(): 97 res = "stop signal: " + status.StopSignal().String() 98 if status.StopSignal() == syscall.SIGTRAP && status.TrapCause() != 0 { 99 res += " (trap " + itoa(status.TrapCause()) + ")" 100 } 101 case status.Continued(): 102 res = "continued" 103 } 104 if status.CoreDump() { 105 res += " (core dumped)" 106 } 107 return res 108 }