aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/os
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2012-03-06 17:57:23 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2012-03-06 17:57:23 +0000
commit593f74bbab63d34c7060918088bcbad686c31c66 (patch)
tree4ce83ca433796a728e9fdd00af105bce158532b5 /libgo/go/os
parent46402cbe0ba3ea92be9642cf18eedaefe57a414c (diff)
downloadgcc-593f74bbab63d34c7060918088bcbad686c31c66.zip
gcc-593f74bbab63d34c7060918088bcbad686c31c66.tar.gz
gcc-593f74bbab63d34c7060918088bcbad686c31c66.tar.bz2
libgo: Update to weekly.2012-03-04 release.
From-SVN: r185010
Diffstat (limited to 'libgo/go/os')
-rw-r--r--libgo/go/os/doc.go72
-rw-r--r--libgo/go/os/exec.go2
-rw-r--r--libgo/go/os/exec_plan9.go44
-rw-r--r--libgo/go/os/exec_posix.go41
-rw-r--r--libgo/go/os/exec_unix.go16
-rw-r--r--libgo/go/os/exec_windows.go40
-rw-r--r--libgo/go/os/file.go2
-rw-r--r--libgo/go/os/os_test.go37
8 files changed, 167 insertions, 87 deletions
diff --git a/libgo/go/os/doc.go b/libgo/go/os/doc.go
index ef857c0..6a531e0 100644
--- a/libgo/go/os/doc.go
+++ b/libgo/go/os/doc.go
@@ -4,6 +4,8 @@
package os
+import "time"
+
// 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.
@@ -11,6 +13,76 @@ func FindProcess(pid int) (p *Process, err error) {
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,
+// rendering it unusable in the future.
+// Release only needs to be called if Wait is not.
+func (p *Process) Release() error {
+ 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.
func Hostname() (name string, err error) {
return hostname()
diff --git a/libgo/go/os/exec.go b/libgo/go/os/exec.go
index 37a0051..531b87c 100644
--- a/libgo/go/os/exec.go
+++ b/libgo/go/os/exec.go
@@ -13,7 +13,7 @@ import (
type Process struct {
Pid int
handle uintptr
- done bool // process has been successfuly waited on
+ done bool // process has been successfully waited on
}
func newProcess(pid int, handle uintptr) *Process {
diff --git a/libgo/go/os/exec_plan9.go b/libgo/go/os/exec_plan9.go
index 1c9e2b9..41cc8c2 100644
--- a/libgo/go/os/exec_plan9.go
+++ b/libgo/go/os/exec_plan9.go
@@ -11,10 +11,7 @@ import (
"time"
)
-// StartProcess starts a new process with the program, arguments and attributes
-// 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) {
+func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
sysattr := &syscall.ProcAttr{
Dir: attr.Dir,
Env: attr.Env,
@@ -40,7 +37,7 @@ 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 errors.New("os: process already finished")
}
@@ -54,8 +51,7 @@ 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 e != nil {
return NewSyscallError("kill", e)
@@ -65,9 +61,7 @@ func (p *Process) Kill() error {
return e
}
-// Wait waits for the Process to exit or stop, and then returns a
-// ProcessState describing its status and an error, if any.
-func (p *Process) Wait() (ps *ProcessState, err error) {
+func (p *Process) wait() (ps *ProcessState, err error) {
var waitmsg syscall.Waitmsg
if p.Pid == -1 {
@@ -94,8 +88,7 @@ func (p *Process) Wait() (ps *ProcessState, err error) {
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
@@ -108,7 +101,7 @@ func findProcess(pid int) (p *Process, err error) {
return newProcess(pid, 0), nil
}
-// ProcessState stores information about process as reported by Wait.
+// 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.
@@ -119,40 +112,27 @@ func (p *ProcessState) Pid() int {
return p.pid
}
-// Exited returns whether the program has exited.
-func (p *ProcessState) Exited() bool {
+func (p *ProcessState) exited() bool {
return p.status.Exited()
}
-// Success reports whether the program exited successfully,
-// such as with exit status 0 on Unix.
-func (p *ProcessState) Success() bool {
+func (p *ProcessState) success() bool {
return p.status.ExitStatus() == 0
}
-// Sys returns system-dependent exit information about
-// 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{} {
+func (p *ProcessState) sys() interface{} {
return p.status
}
-// SysUsage returns system-dependent resource usage information about
-// 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{} {
+func (p *ProcessState) sysUsage() interface{} {
return p.status
}
-// UserTime returns the user CPU time of the exited process and its children.
-// It is always reported as 0 on Windows.
-func (p *ProcessState) UserTime() time.Duration {
+func (p *ProcessState) userTime() time.Duration {
return time.Duration(p.status.Time[0]) * time.Millisecond
}
-// SystemTime returns the system CPU time of the exited process and its children.
-// It is always reported as 0 on Windows.
-func (p *ProcessState) SystemTime() time.Duration {
+func (p *ProcessState) systemTime() time.Duration {
return time.Duration(p.status.Time[1]) * time.Millisecond
}
diff --git a/libgo/go/os/exec_posix.go b/libgo/go/os/exec_posix.go
index 4a75cb67..70351cf 100644
--- a/libgo/go/os/exec_posix.go
+++ b/libgo/go/os/exec_posix.go
@@ -10,14 +10,17 @@ import (
"syscall"
)
-// 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) (p *Process, err error) {
+func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
+ // Double-check existence of the directory we want
+ // to chdir into. We can make the error clearer this way.
+ if attr != nil && attr.Dir != "" {
+ if _, err := Stat(attr.Dir); err != nil {
+ pe := err.(*PathError)
+ pe.Op = "chdir"
+ return nil, pe
+ }
+ }
+
sysattr := &syscall.ProcAttr{
Dir: attr.Dir,
Env: attr.Env,
@@ -37,12 +40,11 @@ func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err e
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)
}
-// ProcessState stores information about process as reported by Wait.
+// ProcessState stores information about a process, as reported by Wait.
type ProcessState struct {
pid int // The process's id.
status syscall.WaitStatus // System-dependent status info.
@@ -54,28 +56,19 @@ func (p *ProcessState) Pid() int {
return p.pid
}
-// Exited returns whether the program has exited.
-func (p *ProcessState) Exited() bool {
+func (p *ProcessState) exited() bool {
return p.status.Exited()
}
-// Success reports whether the program exited successfully,
-// such as with exit status 0 on Unix.
-func (p *ProcessState) Success() bool {
+func (p *ProcessState) success() bool {
return p.status.ExitStatus() == 0
}
-// 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{} {
+func (p *ProcessState) sys() interface{} {
return p.status
}
-// 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{} {
+func (p *ProcessState) sysUsage() interface{} {
return p.rusage
}
diff --git a/libgo/go/os/exec_unix.go b/libgo/go/os/exec_unix.go
index 8d000e9..ecfe535 100644
--- a/libgo/go/os/exec_unix.go
+++ b/libgo/go/os/exec_unix.go
@@ -13,9 +13,7 @@ import (
"time"
)
-// Wait waits for the Process to exit or stop, and then returns a
-// ProcessState describing its status and an error, if any.
-func (p *Process) Wait() (ps *ProcessState, err error) {
+func (p *Process) wait() (ps *ProcessState, err error) {
if p.Pid == -1 {
return nil, syscall.EINVAL
}
@@ -36,8 +34,7 @@ func (p *Process) Wait() (ps *ProcessState, err error) {
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 {
return errors.New("os: process already finished")
}
@@ -51,8 +48,7 @@ func (p *Process) Signal(sig Signal) error {
return nil
}
-// Release releases any resources associated with the Process.
-func (p *Process) Release() error {
+func (p *Process) release() error {
// NOOP for unix.
p.Pid = -1
// no need for a finalizer anymore
@@ -65,12 +61,10 @@ func findProcess(pid int) (p *Process, err error) {
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
}
-// 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
}
diff --git a/libgo/go/os/exec_windows.go b/libgo/go/os/exec_windows.go
index dab0dc9..5beca4a 100644
--- a/libgo/go/os/exec_windows.go
+++ b/libgo/go/os/exec_windows.go
@@ -12,9 +12,7 @@ import (
"unsafe"
)
-// Wait waits for the Process to exit or stop, and then returns a
-// ProcessState describing its status and an error, if any.
-func (p *Process) Wait() (ps *ProcessState, err error) {
+func (p *Process) wait() (ps *ProcessState, err error) {
s, e := syscall.WaitForSingleObject(syscall.Handle(p.handle), syscall.INFINITE)
switch s {
case syscall.WAIT_OBJECT_0:
@@ -29,12 +27,22 @@ func (p *Process) Wait() (ps *ProcessState, err error) {
if e != nil {
return nil, NewSyscallError("GetExitCodeProcess", e)
}
+ var u syscall.Rusage
+ e = syscall.GetProcessTimes(syscall.Handle(p.handle), &u.CreationTime, &u.ExitTime, &u.KernelTime, &u.UserTime)
+ if e != nil {
+ return nil, NewSyscallError("GetProcessTimes", e)
+ }
p.done = true
- return &ProcessState{p.Pid, syscall.WaitStatus{Status: s, ExitCode: ec}, new(syscall.Rusage)}, nil
+ // NOTE(brainman): It seems that sometimes process is not dead
+ // when WaitForSingleObject returns. But we do not know any
+ // other way to wait for it. Sleeping for a while seems to do
+ // the trick sometimes. So we will sleep and smell the roses.
+ defer time.Sleep(5 * time.Millisecond)
+ defer p.Release()
+ return &ProcessState{p.Pid, syscall.WaitStatus{ExitCode: ec}, &u}, 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 {
return errors.New("os: process already finished")
}
@@ -46,8 +54,7 @@ func (p *Process) Signal(sig Signal) error {
return syscall.Errno(syscall.EWINDOWS)
}
-// Release releases any resources associated with the Process.
-func (p *Process) Release() error {
+func (p *Process) release() error {
if p.handle == uintptr(syscall.InvalidHandle) {
return syscall.EINVAL
}
@@ -85,14 +92,15 @@ func init() {
}
}
-// UserTime returns the user CPU time of the exited process and its children.
-// For now, it is always reported as 0 on Windows.
-func (p *ProcessState) UserTime() time.Duration {
- return 0
+func ftToDuration(ft *syscall.Filetime) time.Duration {
+ n := int64(ft.HighDateTime)<<32 + int64(ft.LowDateTime) // in 100-nanosecond intervals
+ return time.Duration(n*100) * time.Nanosecond
+}
+
+func (p *ProcessState) userTime() time.Duration {
+ return ftToDuration(&p.rusage.UserTime)
}
-// SystemTime returns the system CPU time of the exited process and its children.
-// For now, it is always reported as 0 on Windows.
-func (p *ProcessState) SystemTime() time.Duration {
- return 0
+func (p *ProcessState) systemTime() time.Duration {
+ return ftToDuration(&p.rusage.KernelTime)
}
diff --git a/libgo/go/os/file.go b/libgo/go/os/file.go
index 1c3d017..4acf35d 100644
--- a/libgo/go/os/file.go
+++ b/libgo/go/os/file.go
@@ -25,7 +25,7 @@
// open file.go: no such file or directory
//
// The file's data can then be read into a slice of bytes. Read and
-// Write take their byte counts from the length of the artument slice.
+// Write take their byte counts from the length of the argument slice.
//
// data := make([]byte, 100)
// count, err := file.Read(data)
diff --git a/libgo/go/os/os_test.go b/libgo/go/os/os_test.go
index cff35fc..aa01669 100644
--- a/libgo/go/os/os_test.go
+++ b/libgo/go/os/os_test.go
@@ -528,7 +528,6 @@ func exec(t *testing.T, dir, cmd string, args []string, expect string) {
if err != nil {
t.Fatalf("StartProcess: %v", err)
}
- defer p.Release()
w.Close()
var b bytes.Buffer
@@ -846,7 +845,6 @@ func run(t *testing.T, cmd []string) string {
if err != nil {
t.Fatal(err)
}
- defer p.Release()
w.Close()
var b bytes.Buffer
@@ -1012,3 +1010,38 @@ func TestNilProcessStateString(t *testing.T) {
t.Errorf("(*ProcessState)(nil).String() = %q, want %q", s, "<nil>")
}
}
+
+func TestSameFile(t *testing.T) {
+ fa, err := Create("a")
+ if err != nil {
+ t.Fatalf("Create(a): %v", err)
+ }
+ defer Remove(fa.Name())
+ fa.Close()
+ fb, err := Create("b")
+ if err != nil {
+ t.Fatalf("Create(b): %v", err)
+ }
+ defer Remove(fb.Name())
+ fb.Close()
+
+ ia1, err := Stat("a")
+ if err != nil {
+ t.Fatalf("Stat(a): %v", err)
+ }
+ ia2, err := Stat("a")
+ if err != nil {
+ t.Fatalf("Stat(a): %v", err)
+ }
+ if !SameFile(ia1, ia2) {
+ t.Errorf("files should be same")
+ }
+
+ ib, err := Stat("b")
+ if err != nil {
+ t.Fatalf("Stat(b): %v", err)
+ }
+ if SameFile(ia1, ib) {
+ t.Errorf("files should be different")
+ }
+}