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