github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libgo/go/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 terminateProcess(pid, exitcode int) error { 46 h, e := syscall.OpenProcess(syscall.PROCESS_TERMINATE, false, uint32(pid)) 47 if e != nil { 48 return NewSyscallError("OpenProcess", e) 49 } 50 defer syscall.CloseHandle(h) 51 e = syscall.TerminateProcess(h, uint32(exitcode)) 52 return NewSyscallError("TerminateProcess", e) 53 } 54 55 func (p *Process) signal(sig Signal) error { 56 if p.handle == uintptr(syscall.InvalidHandle) { 57 return syscall.EINVAL 58 } 59 if p.done() { 60 return errors.New("os: process already finished") 61 } 62 if sig == Kill { 63 return terminateProcess(p.Pid, 1) 64 } 65 // TODO(rsc): Handle Interrupt too? 66 return syscall.Errno(syscall.EWINDOWS) 67 } 68 69 func (p *Process) release() error { 70 if p.handle == uintptr(syscall.InvalidHandle) { 71 return syscall.EINVAL 72 } 73 e := syscall.CloseHandle(syscall.Handle(p.handle)) 74 if e != nil { 75 return NewSyscallError("CloseHandle", e) 76 } 77 p.handle = uintptr(syscall.InvalidHandle) 78 // no need for a finalizer anymore 79 runtime.SetFinalizer(p, nil) 80 return nil 81 } 82 83 func findProcess(pid int) (p *Process, err error) { 84 const da = syscall.STANDARD_RIGHTS_READ | 85 syscall.PROCESS_QUERY_INFORMATION | syscall.SYNCHRONIZE 86 h, e := syscall.OpenProcess(da, false, uint32(pid)) 87 if e != nil { 88 return nil, NewSyscallError("OpenProcess", e) 89 } 90 return newProcess(pid, uintptr(h)), nil 91 } 92 93 func init() { 94 var argc int32 95 cmd := syscall.GetCommandLine() 96 argv, e := syscall.CommandLineToArgv(cmd, &argc) 97 if e != nil { 98 return 99 } 100 defer syscall.LocalFree(syscall.Handle(uintptr(unsafe.Pointer(argv)))) 101 Args = make([]string, argc) 102 for i, v := range (*argv)[:argc] { 103 Args[i] = string(syscall.UTF16ToString((*v)[:])) 104 } 105 } 106 107 func ftToDuration(ft *syscall.Filetime) time.Duration { 108 n := int64(ft.HighDateTime)<<32 + int64(ft.LowDateTime) // in 100-nanosecond intervals 109 return time.Duration(n*100) * time.Nanosecond 110 } 111 112 func (p *ProcessState) userTime() time.Duration { 113 return ftToDuration(&p.rusage.UserTime) 114 } 115 116 func (p *ProcessState) systemTime() time.Duration { 117 return ftToDuration(&p.rusage.KernelTime) 118 }