github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/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 "errors" 9 "runtime" 10 "syscall" 11 "time" 12 ) 13 14 // The only signal values guaranteed to be present on all systems 15 // are Interrupt (send the process an interrupt) and Kill (force 16 // the process to exit). 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 for _, f := range attr.Files { 30 sysattr.Files = append(sysattr.Files, f.Fd()) 31 } 32 33 pid, h, e := syscall.StartProcess(name, argv, sysattr) 34 if e != nil { 35 return nil, &PathError{"fork/exec", name, e} 36 } 37 38 return newProcess(pid, h), nil 39 } 40 41 func (p *Process) writeProcFile(file string, data string) error { 42 f, e := OpenFile("/proc/"+itoa(p.Pid)+"/"+file, O_WRONLY, 0) 43 if e != nil { 44 return e 45 } 46 defer f.Close() 47 _, e = f.Write([]byte(data)) 48 return e 49 } 50 51 func (p *Process) signal(sig Signal) error { 52 if p.done() { 53 return errors.New("os: process already finished") 54 } 55 if e := p.writeProcFile("note", sig.String()); e != nil { 56 return NewSyscallError("signal", e) 57 } 58 return nil 59 } 60 61 func (p *Process) kill() error { 62 return p.signal(Kill) 63 } 64 65 func (p *Process) wait() (ps *ProcessState, err error) { 66 var waitmsg syscall.Waitmsg 67 68 if p.Pid == -1 { 69 return nil, ErrInvalid 70 } 71 err = syscall.WaitProcess(p.Pid, &waitmsg) 72 if err != nil { 73 return nil, NewSyscallError("wait", err) 74 } 75 76 p.setDone() 77 ps = &ProcessState{ 78 pid: waitmsg.Pid, 79 status: &waitmsg, 80 } 81 return ps, nil 82 } 83 84 func (p *Process) release() error { 85 // NOOP for Plan 9. 86 p.Pid = -1 87 // no need for a finalizer anymore 88 runtime.SetFinalizer(p, nil) 89 return nil 90 } 91 92 func findProcess(pid int) (p *Process, err error) { 93 // NOOP for Plan 9. 94 return newProcess(pid, 0), nil 95 } 96 97 // ProcessState stores information about a process, as reported by Wait. 98 type ProcessState struct { 99 pid int // The process's id. 100 status *syscall.Waitmsg // System-dependent status info. 101 } 102 103 // Pid returns the process id of the exited process. 104 func (p *ProcessState) Pid() int { 105 return p.pid 106 } 107 108 func (p *ProcessState) exited() bool { 109 return p.status.Exited() 110 } 111 112 func (p *ProcessState) success() bool { 113 return p.status.ExitStatus() == 0 114 } 115 116 func (p *ProcessState) sys() interface{} { 117 return p.status 118 } 119 120 func (p *ProcessState) sysUsage() interface{} { 121 return p.status 122 } 123 124 func (p *ProcessState) userTime() time.Duration { 125 return time.Duration(p.status.Time[0]) * time.Millisecond 126 } 127 128 func (p *ProcessState) systemTime() time.Duration { 129 return time.Duration(p.status.Time[1]) * time.Millisecond 130 } 131 132 func (p *ProcessState) String() string { 133 if p == nil { 134 return "<nil>" 135 } 136 return "exit status: " + p.status.Msg 137 }