github.com/zxy12/go_duplicate_112_new@v0.0.0-20200807091221-747231827200/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 aix darwin dragonfly freebsd js,wasm 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 on all 14 // systems are os.Interrupt (send the process an interrupt) and os.Kill (force 15 // the process to exit). On Windows, sending os.Interrupt to a process with 16 // os.Process.Signal is not implemented; it will return an error instead of 17 // sending a signal. 18 var ( 19 Interrupt Signal = syscall.SIGINT 20 Kill Signal = syscall.SIGKILL 21 ) 22 23 func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) { 24 // If there is no SysProcAttr (ie. no Chroot or changed 25 // UID/GID), double-check existence of the directory we want 26 // to chdir into. We can make the error clearer this way. 27 if attr != nil && attr.Sys == nil && attr.Dir != "" { 28 if _, err := Stat(attr.Dir); err != nil { 29 pe := err.(*PathError) 30 pe.Op = "chdir" 31 return nil, pe 32 } 33 } 34 35 sysattr := &syscall.ProcAttr{ 36 Dir: attr.Dir, 37 Env: attr.Env, 38 Sys: attr.Sys, 39 } 40 if sysattr.Env == nil { 41 sysattr.Env, err = environForSysProcAttr(sysattr.Sys) 42 if err != nil { 43 return nil, err 44 } 45 } 46 for _, f := range attr.Files { 47 sysattr.Files = append(sysattr.Files, f.Fd()) 48 } 49 50 pid, h, e := syscall.StartProcess(name, argv, sysattr) 51 if e != nil { 52 return nil, &PathError{"fork/exec", name, e} 53 } 54 return newProcess(pid, h), nil 55 } 56 57 func (p *Process) kill() error { 58 return p.Signal(Kill) 59 } 60 61 // ProcessState stores information about a process, as reported by Wait. 62 type ProcessState struct { 63 pid int // The process's id. 64 status syscall.WaitStatus // System-dependent status info. 65 rusage *syscall.Rusage 66 } 67 68 // Pid returns the process id of the exited process. 69 func (p *ProcessState) Pid() int { 70 return p.pid 71 } 72 73 func (p *ProcessState) exited() bool { 74 return p.status.Exited() 75 } 76 77 func (p *ProcessState) success() bool { 78 return p.status.ExitStatus() == 0 79 } 80 81 func (p *ProcessState) sys() interface{} { 82 return p.status 83 } 84 85 func (p *ProcessState) sysUsage() interface{} { 86 return p.rusage 87 } 88 89 func (p *ProcessState) String() string { 90 if p == nil { 91 return "<nil>" 92 } 93 status := p.Sys().(syscall.WaitStatus) 94 res := "" 95 switch { 96 case status.Exited(): 97 res = "exit status " + itoa(status.ExitStatus()) 98 case status.Signaled(): 99 res = "signal: " + status.Signal().String() 100 case status.Stopped(): 101 res = "stop signal: " + status.StopSignal().String() 102 if status.StopSignal() == syscall.SIGTRAP && status.TrapCause() != 0 { 103 res += " (trap " + itoa(status.TrapCause()) + ")" 104 } 105 case status.Continued(): 106 res = "continued" 107 } 108 if status.CoreDump() { 109 res += " (core dumped)" 110 } 111 return res 112 } 113 114 // ExitCode returns the exit code of the exited process, or -1 115 // if the process hasn't exited or was terminated by a signal. 116 func (p *ProcessState) ExitCode() int { 117 // return -1 if the process hasn't started. 118 if p == nil { 119 return -1 120 } 121 return p.status.ExitStatus() 122 }