github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/os/exec_plan9.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 package os 6 7 import ( 8 "runtime" 9 "syscall" 10 "time" 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.Note("interrupt") 19 Kill Signal = syscall.Note("kill") 20 ) 21 22 func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) { 23 sysattr := &syscall.ProcAttr{ 24 Dir: attr.Dir, 25 Env: attr.Env, 26 Sys: attr.Sys, 27 } 28 29 sysattr.Files = make([]uintptr, 0, len(attr.Files)) 30 for _, f := range attr.Files { 31 sysattr.Files = append(sysattr.Files, f.Fd()) 32 } 33 34 pid, h, e := syscall.StartProcess(name, argv, sysattr) 35 if e != nil { 36 return nil, &PathError{Op: "fork/exec", Path: name, Err: e} 37 } 38 39 return newProcess(pid, h), nil 40 } 41 42 func (p *Process) writeProcFile(file string, data string) error { 43 f, e := OpenFile("/proc/"+itoa(p.Pid)+"/"+file, O_WRONLY, 0) 44 if e != nil { 45 return e 46 } 47 defer f.Close() 48 _, e = f.Write([]byte(data)) 49 return e 50 } 51 52 func (p *Process) signal(sig Signal) error { 53 if p.done() { 54 return ErrProcessDone 55 } 56 if e := p.writeProcFile("note", sig.String()); e != nil { 57 return NewSyscallError("signal", e) 58 } 59 return nil 60 } 61 62 func (p *Process) kill() error { 63 return p.signal(Kill) 64 } 65 66 func (p *Process) wait() (ps *ProcessState, err error) { 67 var waitmsg syscall.Waitmsg 68 69 if p.Pid == -1 { 70 return nil, ErrInvalid 71 } 72 err = syscall.WaitProcess(p.Pid, &waitmsg) 73 if err != nil { 74 return nil, NewSyscallError("wait", err) 75 } 76 77 p.setDone() 78 ps = &ProcessState{ 79 pid: waitmsg.Pid, 80 status: &waitmsg, 81 } 82 return ps, nil 83 } 84 85 func (p *Process) release() error { 86 // NOOP for Plan 9. 87 p.Pid = -1 88 // no need for a finalizer anymore 89 runtime.SetFinalizer(p, nil) 90 return nil 91 } 92 93 func findProcess(pid int) (p *Process, err error) { 94 // NOOP for Plan 9. 95 return newProcess(pid, 0), nil 96 } 97 98 // ProcessState stores information about a process, as reported by Wait. 99 type ProcessState struct { 100 pid int // The process's id. 101 status *syscall.Waitmsg // System-dependent status info. 102 } 103 104 // Pid returns the process id of the exited process. 105 func (p *ProcessState) Pid() int { 106 return p.pid 107 } 108 109 func (p *ProcessState) exited() bool { 110 return p.status.Exited() 111 } 112 113 func (p *ProcessState) success() bool { 114 return p.status.ExitStatus() == 0 115 } 116 117 func (p *ProcessState) sys() interface{} { 118 return p.status 119 } 120 121 func (p *ProcessState) sysUsage() interface{} { 122 return p.status 123 } 124 125 func (p *ProcessState) userTime() time.Duration { 126 return time.Duration(p.status.Time[0]) * time.Millisecond 127 } 128 129 func (p *ProcessState) systemTime() time.Duration { 130 return time.Duration(p.status.Time[1]) * time.Millisecond 131 } 132 133 func (p *ProcessState) String() string { 134 if p == nil { 135 return "<nil>" 136 } 137 return "exit status: " + p.status.Msg 138 } 139 140 // ExitCode returns the exit code of the exited process, or -1 141 // if the process hasn't exited or was terminated by a signal. 142 func (p *ProcessState) ExitCode() int { 143 // return -1 if the process hasn't started. 144 if p == nil { 145 return -1 146 } 147 return p.status.ExitStatus() 148 }