github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/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 = Environ() 42 } 43 for _, f := range attr.Files { 44 sysattr.Files = append(sysattr.Files, f.Fd()) 45 } 46 47 pid, h, e := syscall.StartProcess(name, argv, sysattr) 48 if e != nil { 49 return nil, &PathError{"fork/exec", name, e} 50 } 51 return newProcess(pid, h), nil 52 } 53 54 func (p *Process) kill() error { 55 return p.Signal(Kill) 56 } 57 58 // ProcessState stores information about a process, as reported by Wait. 59 type ProcessState struct { 60 pid int // The process's id. 61 status syscall.WaitStatus // System-dependent status info. 62 rusage *syscall.Rusage 63 } 64 65 // Pid returns the process id of the exited process. 66 func (p *ProcessState) Pid() int { 67 return p.pid 68 } 69 70 func (p *ProcessState) exited() bool { 71 return p.status.Exited() 72 } 73 74 func (p *ProcessState) success() bool { 75 return p.status.ExitStatus() == 0 76 } 77 78 func (p *ProcessState) sys() interface{} { 79 return p.status 80 } 81 82 func (p *ProcessState) sysUsage() interface{} { 83 return p.rusage 84 } 85 86 func (p *ProcessState) String() string { 87 if p == nil { 88 return "<nil>" 89 } 90 status := p.Sys().(syscall.WaitStatus) 91 res := "" 92 switch { 93 case status.Exited(): 94 res = "exit status " + itoa(status.ExitStatus()) 95 case status.Signaled(): 96 res = "signal: " + status.Signal().String() 97 case status.Stopped(): 98 res = "stop signal: " + status.StopSignal().String() 99 if status.StopSignal() == syscall.SIGTRAP && status.TrapCause() != 0 { 100 res += " (trap " + itoa(status.TrapCause()) + ")" 101 } 102 case status.Continued(): 103 res = "continued" 104 } 105 if status.CoreDump() { 106 res += " (core dumped)" 107 } 108 return res 109 } 110 111 // ExitCode returns the exit code of the exited process, or -1 112 // if the process hasn't exited or was terminated by a signal. 113 func (p *ProcessState) ExitCode() int { 114 // return -1 if the process hasn't started. 115 if p == nil { 116 return -1 117 } 118 return p.status.ExitStatus() 119 }