github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/os/exec_windows.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 "errors" 9 "runtime" 10 "syscall" 11 "time" 12 "unsafe" 13 ) 14 15 func (p *Process) wait() (ps *ProcessState, err error) { 16 s, e := syscall.WaitForSingleObject(syscall.Handle(p.handle), syscall.INFINITE) 17 switch s { 18 case syscall.WAIT_OBJECT_0: 19 break 20 case syscall.WAIT_FAILED: 21 return nil, NewSyscallError("WaitForSingleObject", e) 22 default: 23 return nil, errors.New("os: unexpected result from WaitForSingleObject") 24 } 25 var ec uint32 26 e = syscall.GetExitCodeProcess(syscall.Handle(p.handle), &ec) 27 if e != nil { 28 return nil, NewSyscallError("GetExitCodeProcess", e) 29 } 30 var u syscall.Rusage 31 e = syscall.GetProcessTimes(syscall.Handle(p.handle), &u.CreationTime, &u.ExitTime, &u.KernelTime, &u.UserTime) 32 if e != nil { 33 return nil, NewSyscallError("GetProcessTimes", e) 34 } 35 p.setDone() 36 // NOTE(brainman): It seems that sometimes process is not dead 37 // when WaitForSingleObject returns. But we do not know any 38 // other way to wait for it. Sleeping for a while seems to do 39 // the trick sometimes. So we will sleep and smell the roses. 40 defer time.Sleep(5 * time.Millisecond) 41 defer p.Release() 42 return &ProcessState{p.Pid, syscall.WaitStatus{ExitCode: ec}, &u}, nil 43 } 44 45 func (p *Process) signal(sig Signal) error { 46 if p.done() { 47 return errors.New("os: process already finished") 48 } 49 if sig == Kill { 50 e := syscall.TerminateProcess(syscall.Handle(p.handle), 1) 51 return NewSyscallError("TerminateProcess", e) 52 } 53 // TODO(rsc): Handle Interrupt too? 54 return syscall.Errno(syscall.EWINDOWS) 55 } 56 57 func (p *Process) release() error { 58 if p.handle == uintptr(syscall.InvalidHandle) { 59 return syscall.EINVAL 60 } 61 e := syscall.CloseHandle(syscall.Handle(p.handle)) 62 if e != nil { 63 return NewSyscallError("CloseHandle", e) 64 } 65 p.handle = uintptr(syscall.InvalidHandle) 66 // no need for a finalizer anymore 67 runtime.SetFinalizer(p, nil) 68 return nil 69 } 70 71 func findProcess(pid int) (p *Process, err error) { 72 const da = syscall.STANDARD_RIGHTS_READ | 73 syscall.PROCESS_QUERY_INFORMATION | syscall.SYNCHRONIZE 74 h, e := syscall.OpenProcess(da, false, uint32(pid)) 75 if e != nil { 76 return nil, NewSyscallError("OpenProcess", e) 77 } 78 return newProcess(pid, uintptr(h)), nil 79 } 80 81 func init() { 82 var argc int32 83 cmd := syscall.GetCommandLine() 84 argv, e := syscall.CommandLineToArgv(cmd, &argc) 85 if e != nil { 86 return 87 } 88 defer syscall.LocalFree(syscall.Handle(uintptr(unsafe.Pointer(argv)))) 89 Args = make([]string, argc) 90 for i, v := range (*argv)[:argc] { 91 Args[i] = string(syscall.UTF16ToString((*v)[:])) 92 } 93 } 94 95 func ftToDuration(ft *syscall.Filetime) time.Duration { 96 n := int64(ft.HighDateTime)<<32 + int64(ft.LowDateTime) // in 100-nanosecond intervals 97 return time.Duration(n*100) * time.Nanosecond 98 } 99 100 func (p *ProcessState) userTime() time.Duration { 101 return ftToDuration(&p.rusage.UserTime) 102 } 103 104 func (p *ProcessState) systemTime() time.Duration { 105 return ftToDuration(&p.rusage.KernelTime) 106 }