diff options
Diffstat (limited to 'src/pkg/os/exec_plan9.go')
-rw-r--r-- | src/pkg/os/exec_plan9.go | 125 |
1 files changed, 58 insertions, 67 deletions
diff --git a/src/pkg/os/exec_plan9.go b/src/pkg/os/exec_plan9.go index 6f0722a22..41cc8c26f 100644 --- a/src/pkg/os/exec_plan9.go +++ b/src/pkg/os/exec_plan9.go @@ -5,33 +5,25 @@ package os import ( + "errors" "runtime" "syscall" + "time" ) -// StartProcess starts a new process with the program, arguments and attributes -// specified by name, argv and attr. -func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err Error) { +func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) { sysattr := &syscall.ProcAttr{ Dir: attr.Dir, Env: attr.Env, Sys: attr.Sys, } - // Create array of integer (system) fds. - intfd := make([]int, len(attr.Files)) - for i, f := range attr.Files { - if f == nil { - intfd[i] = -1 - } else { - intfd[i] = f.Fd() - } + for _, f := range attr.Files { + sysattr.Files = append(sysattr.Files, f.Fd()) } - sysattr.Files = intfd - pid, h, e := syscall.StartProcess(name, argv, sysattr) - if iserror(e) { + if e != nil { return nil, &PathError{"fork/exec", name, e} } @@ -45,13 +37,13 @@ func (note Plan9Note) String() string { return string(note) } -func (p *Process) Signal(sig Signal) Error { +func (p *Process) signal(sig Signal) error { if p.done { - return NewError("os: process already finished") + return errors.New("os: process already finished") } f, e := OpenFile("/proc/"+itoa(p.Pid)+"/note", O_WRONLY, 0) - if iserror(e) { + if e != nil { return NewSyscallError("signal", e) } defer f.Close() @@ -59,10 +51,9 @@ func (p *Process) Signal(sig Signal) Error { return e } -// Kill causes the Process to exit immediately. -func (p *Process) Kill() Error { +func (p *Process) kill() error { f, e := OpenFile("/proc/"+itoa(p.Pid)+"/ctl", O_WRONLY, 0) - if iserror(e) { + if e != nil { return NewSyscallError("kill", e) } defer f.Close() @@ -70,38 +61,17 @@ func (p *Process) Kill() Error { return e } -// Exec replaces the current process with an execution of the -// named binary, with arguments argv and environment envv. -// If successful, Exec never returns. If it fails, it returns an Error. -// ForkExec is almost always a better way to execute a program. -func Exec(name string, argv []string, envv []string) Error { - e := syscall.Exec(name, argv, envv) - if iserror(e) { - return &PathError{"exec", name, e} - } - - return nil -} - -// Waitmsg stores the information about an exited process as reported by Wait. -type Waitmsg struct { - syscall.Waitmsg -} - -// Wait waits for the Process to exit or stop, and then returns a -// Waitmsg describing its status and an Error, if any. The options -// (WNOHANG etc.) affect the behavior of the Wait call. -func (p *Process) Wait(options int) (w *Waitmsg, err Error) { +func (p *Process) wait() (ps *ProcessState, err error) { var waitmsg syscall.Waitmsg if p.Pid == -1 { - return nil, EINVAL + return nil, ErrInvalid } for true { err = syscall.Await(&waitmsg) - if iserror(err) { + if err != nil { return nil, NewSyscallError("wait", err) } @@ -111,25 +81,14 @@ func (p *Process) Wait(options int) (w *Waitmsg, err Error) { } } - return &Waitmsg{waitmsg}, nil -} - -// Wait waits for process pid to exit or stop, and then returns a -// Waitmsg describing its status and an Error, if any. The options -// (WNOHANG etc.) affect the behavior of the Wait call. -// Wait is equivalent to calling FindProcess and then Wait -// and Release on the result. -func Wait(pid int, options int) (w *Waitmsg, err Error) { - p, e := FindProcess(pid) - if e != nil { - return nil, e + ps = &ProcessState{ + pid: waitmsg.Pid, + status: &waitmsg, } - defer p.Release() - return p.Wait(options) + return ps, nil } -// Release releases any resources associated with the Process. -func (p *Process) Release() Error { +func (p *Process) release() error { // NOOP for Plan 9. p.Pid = -1 // no need for a finalizer anymore @@ -137,17 +96,49 @@ func (p *Process) Release() Error { return nil } -// FindProcess looks for a running process by its pid. -// The Process it returns can be used to obtain information -// about the underlying operating system process. -func FindProcess(pid int) (p *Process, err Error) { +func findProcess(pid int) (p *Process, err error) { // NOOP for Plan 9. return newProcess(pid, 0), nil } -func (w *Waitmsg) String() string { - if w == nil { +// ProcessState stores information about a process, as reported by Wait. +type ProcessState struct { + pid int // The process's id. + status *syscall.Waitmsg // System-dependent status info. +} + +// Pid returns the process id of the exited process. +func (p *ProcessState) Pid() int { + return p.pid +} + +func (p *ProcessState) exited() bool { + return p.status.Exited() +} + +func (p *ProcessState) success() bool { + return p.status.ExitStatus() == 0 +} + +func (p *ProcessState) sys() interface{} { + return p.status +} + +func (p *ProcessState) sysUsage() interface{} { + return p.status +} + +func (p *ProcessState) userTime() time.Duration { + return time.Duration(p.status.Time[0]) * time.Millisecond +} + +func (p *ProcessState) systemTime() time.Duration { + return time.Duration(p.status.Time[1]) * time.Millisecond +} + +func (p *ProcessState) String() string { + if p == nil { return "<nil>" } - return "exit status: " + w.Msg + return "exit status: " + p.status.Msg } |