Commit 30db6d41 authored by Russ Cox's avatar Russ Cox

os: centralize documentation of Process and ProcessState

Also change Wait to say "exit" instead of "exit or stop".

I notice that Pid is not implemented on all systems.
Should we fix that?

Fixes #3138.

R=golang-dev, alex.brainman, r
CC=golang-dev
https://golang.org/cl/5710056
parent 47d614e6
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
package os package os
import "time"
// FindProcess looks for a running process by its pid. // FindProcess looks for a running process by its pid.
// The Process it returns can be used to obtain information // The Process it returns can be used to obtain information
// about the underlying operating system process. // about the underlying operating system process.
...@@ -11,6 +13,17 @@ func FindProcess(pid int) (p *Process, err error) { ...@@ -11,6 +13,17 @@ func FindProcess(pid int) (p *Process, err error) {
return findProcess(pid) return findProcess(pid)
} }
// StartProcess starts a new process with the program, arguments and attributes
// specified by name, argv and attr.
//
// StartProcess is a low-level interface. The os/exec package provides
// higher-level interfaces.
//
// If there is an error, it will be of type *PathError.
func StartProcess(name string, argv []string, attr *ProcAttr) (*Process, error) {
return startProcess(name, argv, attr)
}
// Release releases any resources associated with the Process p, // Release releases any resources associated with the Process p,
// rendering it unusable in the future. // rendering it unusable in the future.
// Release only needs to be called if Wait is not. // Release only needs to be called if Wait is not.
...@@ -18,6 +31,58 @@ func (p *Process) Release() error { ...@@ -18,6 +31,58 @@ func (p *Process) Release() error {
return p.release() return p.release()
} }
// Kill causes the Process to exit immediately.
func (p *Process) Kill() error {
return p.kill()
}
// Wait waits for the Process to exit, and then returns a
// ProcessState describing its status and an error, if any.
// Wait releases any resources associated with the Process.
func (p *Process) Wait() (*ProcessState, error) {
return p.wait()
}
// Signal sends a signal to the Process.
func (p *Process) Signal(sig Signal) error {
return p.signal(sig)
}
// UserTime returns the user CPU time of the exited process and its children.
func (p *ProcessState) UserTime() time.Duration {
return p.userTime()
}
// SystemTime returns the system CPU time of the exited process and its children.
func (p *ProcessState) SystemTime() time.Duration {
return p.systemTime()
}
// Exited returns whether the program has exited.
func (p *ProcessState) Exited() bool {
return p.exited()
}
// Success reports whether the program exited successfully,
// such as with exit status 0 on Unix.
func (p *ProcessState) Success() bool {
return p.success()
}
// Sys returns system-dependent exit information about
// the process. Convert it to the appropriate underlying
// type, such as syscall.WaitStatus on Unix, to access its contents.
func (p *ProcessState) Sys() interface{} {
return p.sys()
}
// SysUsage returns system-dependent resource usage information about
// the exited process. Convert it to the appropriate underlying
// type, such as *syscall.Rusage on Unix, to access its contents.
func (p *ProcessState) SysUsage() interface{} {
return p.sysUsage()
}
// Hostname returns the host name reported by the kernel. // Hostname returns the host name reported by the kernel.
func Hostname() (name string, err error) { func Hostname() (name string, err error) {
return hostname() return hostname()
......
...@@ -11,10 +11,7 @@ import ( ...@@ -11,10 +11,7 @@ import (
"time" "time"
) )
// StartProcess starts a new process with the program, arguments and attributes func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
// specified by name, argv and attr.
// If there is an error, it will be of type *PathError.
func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
sysattr := &syscall.ProcAttr{ sysattr := &syscall.ProcAttr{
Dir: attr.Dir, Dir: attr.Dir,
Env: attr.Env, Env: attr.Env,
...@@ -40,7 +37,7 @@ func (note Plan9Note) String() string { ...@@ -40,7 +37,7 @@ func (note Plan9Note) String() string {
return string(note) return string(note)
} }
func (p *Process) Signal(sig Signal) error { func (p *Process) signal(sig Signal) error {
if p.done { if p.done {
return errors.New("os: process already finished") return errors.New("os: process already finished")
} }
...@@ -54,8 +51,7 @@ func (p *Process) Signal(sig Signal) error { ...@@ -54,8 +51,7 @@ func (p *Process) Signal(sig Signal) error {
return e 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) f, e := OpenFile("/proc/"+itoa(p.Pid)+"/ctl", O_WRONLY, 0)
if e != nil { if e != nil {
return NewSyscallError("kill", e) return NewSyscallError("kill", e)
...@@ -65,9 +61,7 @@ func (p *Process) Kill() error { ...@@ -65,9 +61,7 @@ func (p *Process) Kill() error {
return e return e
} }
// Wait waits for the Process to exit or stop, and then returns a func (p *Process) wait() (ps *ProcessState, err error) {
// ProcessState describing its status and an error, if any.
func (p *Process) Wait() (ps *ProcessState, err error) {
var waitmsg syscall.Waitmsg var waitmsg syscall.Waitmsg
if p.Pid == -1 { if p.Pid == -1 {
...@@ -118,40 +112,27 @@ func (p *ProcessState) Pid() int { ...@@ -118,40 +112,27 @@ func (p *ProcessState) Pid() int {
return p.pid return p.pid
} }
// Exited returns whether the program has exited. func (p *ProcessState) exited() bool {
func (p *ProcessState) Exited() bool {
return p.status.Exited() return p.status.Exited()
} }
// Success reports whether the program exited successfully, func (p *ProcessState) success() bool {
// such as with exit status 0 on Unix.
func (p *ProcessState) Success() bool {
return p.status.ExitStatus() == 0 return p.status.ExitStatus() == 0
} }
// Sys returns system-dependent exit information about func (p *ProcessState) sys() interface{} {
// the process. Convert it to the appropriate underlying
// type, such as *syscall.Waitmsg on Plan 9, to access its contents.
func (p *ProcessState) Sys() interface{} {
return p.status return p.status
} }
// SysUsage returns system-dependent resource usage information about func (p *ProcessState) sysUsage() interface{} {
// the exited process. Convert it to the appropriate underlying
// type, such as *syscall.Waitmsg on Plan 9, to access its contents.
func (p *ProcessState) SysUsage() interface{} {
return p.status return p.status
} }
// UserTime returns the user CPU time of the exited process and its children. func (p *ProcessState) userTime() time.Duration {
// It is always reported as 0 on Windows.
func (p *ProcessState) UserTime() time.Duration {
return time.Duration(p.status.Time[0]) * time.Millisecond return time.Duration(p.status.Time[0]) * time.Millisecond
} }
// SystemTime returns the system CPU time of the exited process and its children. func (p *ProcessState) systemTime() time.Duration {
// It is always reported as 0 on Windows.
func (p *ProcessState) SystemTime() time.Duration {
return time.Duration(p.status.Time[1]) * time.Millisecond return time.Duration(p.status.Time[1]) * time.Millisecond
} }
......
...@@ -10,14 +10,7 @@ import ( ...@@ -10,14 +10,7 @@ import (
"syscall" "syscall"
) )
// StartProcess starts a new process with the program, arguments and attributes func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
// specified by name, argv and attr.
//
// StartProcess is a low-level interface. The os/exec package provides
// higher-level interfaces.
//
// If there is an error, it will be of type *PathError.
func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
// Double-check existence of the directory we want // Double-check existence of the directory we want
// to chdir into. We can make the error clearer this way. // to chdir into. We can make the error clearer this way.
if attr != nil && attr.Dir != "" { if attr != nil && attr.Dir != "" {
...@@ -47,8 +40,7 @@ func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err e ...@@ -47,8 +40,7 @@ func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err e
return newProcess(pid, h), nil return newProcess(pid, h), nil
} }
// Kill causes the Process to exit immediately. func (p *Process) kill() error {
func (p *Process) Kill() error {
return p.Signal(Kill) return p.Signal(Kill)
} }
...@@ -64,28 +56,19 @@ func (p *ProcessState) Pid() int { ...@@ -64,28 +56,19 @@ func (p *ProcessState) Pid() int {
return p.pid return p.pid
} }
// Exited returns whether the program has exited. func (p *ProcessState) exited() bool {
func (p *ProcessState) Exited() bool {
return p.status.Exited() return p.status.Exited()
} }
// Success reports whether the program exited successfully, func (p *ProcessState) success() bool {
// such as with exit status 0 on Unix.
func (p *ProcessState) Success() bool {
return p.status.ExitStatus() == 0 return p.status.ExitStatus() == 0
} }
// Sys returns system-dependent exit information about func (p *ProcessState) sys() interface{} {
// the process. Convert it to the appropriate underlying
// type, such as syscall.WaitStatus on Unix, to access its contents.
func (p *ProcessState) Sys() interface{} {
return p.status return p.status
} }
// SysUsage returns system-dependent resource usage information about func (p *ProcessState) sysUsage() interface{} {
// the exited process. Convert it to the appropriate underlying
// type, such as *syscall.Rusage on Unix, to access its contents.
func (p *ProcessState) SysUsage() interface{} {
return p.rusage return p.rusage
} }
......
...@@ -13,9 +13,7 @@ import ( ...@@ -13,9 +13,7 @@ import (
"time" "time"
) )
// Wait waits for the Process to exit or stop, and then returns a func (p *Process) wait() (ps *ProcessState, err error) {
// ProcessState describing its status and an error, if any.
func (p *Process) Wait() (ps *ProcessState, err error) {
if p.Pid == -1 { if p.Pid == -1 {
return nil, syscall.EINVAL return nil, syscall.EINVAL
} }
...@@ -36,8 +34,7 @@ func (p *Process) Wait() (ps *ProcessState, err error) { ...@@ -36,8 +34,7 @@ func (p *Process) Wait() (ps *ProcessState, err error) {
return ps, nil return ps, nil
} }
// Signal sends a signal to the Process. func (p *Process) signal(sig Signal) error {
func (p *Process) Signal(sig Signal) error {
if p.done { if p.done {
return errors.New("os: process already finished") return errors.New("os: process already finished")
} }
...@@ -64,12 +61,10 @@ func findProcess(pid int) (p *Process, err error) { ...@@ -64,12 +61,10 @@ func findProcess(pid int) (p *Process, err error) {
return newProcess(pid, 0), nil return newProcess(pid, 0), nil
} }
// UserTime returns the user CPU time of the exited process and its children. func (p *ProcessState) userTime() time.Duration {
func (p *ProcessState) UserTime() time.Duration {
return time.Duration(p.rusage.Utime.Nano()) * time.Nanosecond return time.Duration(p.rusage.Utime.Nano()) * time.Nanosecond
} }
// SystemTime returns the system CPU time of the exited process and its children. func (p *ProcessState) systemTime() time.Duration {
func (p *ProcessState) SystemTime() time.Duration {
return time.Duration(p.rusage.Stime.Nano()) * time.Nanosecond return time.Duration(p.rusage.Stime.Nano()) * time.Nanosecond
} }
...@@ -12,10 +12,7 @@ import ( ...@@ -12,10 +12,7 @@ import (
"unsafe" "unsafe"
) )
// Wait waits for the Process to exit or stop, and then returns a func (p *Process) wait() (ps *ProcessState, err error) {
// ProcessState describing its status and an error, if any.
// Wait releases any resources associated with the Process.
func (p *Process) Wait() (ps *ProcessState, err error) {
s, e := syscall.WaitForSingleObject(syscall.Handle(p.handle), syscall.INFINITE) s, e := syscall.WaitForSingleObject(syscall.Handle(p.handle), syscall.INFINITE)
switch s { switch s {
case syscall.WAIT_OBJECT_0: case syscall.WAIT_OBJECT_0:
...@@ -35,8 +32,7 @@ func (p *Process) Wait() (ps *ProcessState, err error) { ...@@ -35,8 +32,7 @@ func (p *Process) Wait() (ps *ProcessState, err error) {
return &ProcessState{p.Pid, syscall.WaitStatus{Status: s, ExitCode: ec}, new(syscall.Rusage)}, nil return &ProcessState{p.Pid, syscall.WaitStatus{Status: s, ExitCode: ec}, new(syscall.Rusage)}, nil
} }
// Signal sends a signal to the Process. func (p *Process) signal(sig Signal) error {
func (p *Process) Signal(sig Signal) error {
if p.done { if p.done {
return errors.New("os: process already finished") return errors.New("os: process already finished")
} }
...@@ -86,14 +82,12 @@ func init() { ...@@ -86,14 +82,12 @@ func init() {
} }
} }
// UserTime returns the user CPU time of the exited process and its children. // BUG(rsc): On Windows, ProcessState's UserTime and SystemTime methods always return 0.
// For now, it is always reported as 0 on Windows.
func (p *ProcessState) UserTime() time.Duration { func (p *ProcessState) userTime() time.Duration {
return 0 return 0
} }
// SystemTime returns the system CPU time of the exited process and its children. func (p *ProcessState) systemTime() time.Duration {
// For now, it is always reported as 0 on Windows.
func (p *ProcessState) SystemTime() time.Duration {
return 0 return 0
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment