aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/os/exec_windows.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/os/exec_windows.go')
-rw-r--r--libgo/go/os/exec_windows.go42
1 files changed, 32 insertions, 10 deletions
diff --git a/libgo/go/os/exec_windows.go b/libgo/go/os/exec_windows.go
index 9463d2c0e3f..5beca4a6509 100644
--- a/libgo/go/os/exec_windows.go
+++ b/libgo/go/os/exec_windows.go
@@ -8,12 +8,11 @@ import (
"errors"
"runtime"
"syscall"
+ "time"
"unsafe"
)
-// Wait waits for the Process to exit or stop, and then returns a
-// Waitmsg describing its status and an error, if any.
-func (p *Process) Wait(options int) (w *Waitmsg, 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:
@@ -28,26 +27,36 @@ func (p *Process) Wait(options int) (w *Waitmsg, 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 &Waitmsg{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")
}
- if us, ok := sig.(UnixSignal); ok && us == syscall.SIGKILL {
+ if sig == Kill {
e := syscall.TerminateProcess(syscall.Handle(p.handle), 1)
return NewSyscallError("TerminateProcess", e)
}
+ // TODO(rsc): Handle Interrupt too?
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 EINVAL
+ return syscall.EINVAL
}
e := syscall.CloseHandle(syscall.Handle(p.handle))
if e != nil {
@@ -82,3 +91,16 @@ func init() {
Args[i] = string(syscall.UTF16ToString((*v)[:]))
}
}
+
+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)
+}
+
+func (p *ProcessState) systemTime() time.Duration {
+ return ftToDuration(&p.rusage.KernelTime)
+}