Source file
src/os/exec_windows.go
1
2
3
4
5 package os
6
7 import (
8 "errors"
9 "internal/syscall/windows"
10 "runtime"
11 "sync/atomic"
12 "syscall"
13 "time"
14 )
15
16 func (p *Process) wait() (ps *ProcessState, err error) {
17 handle := atomic.LoadUintptr(&p.handle)
18 s, e := syscall.WaitForSingleObject(syscall.Handle(handle), syscall.INFINITE)
19 switch s {
20 case syscall.WAIT_OBJECT_0:
21 break
22 case syscall.WAIT_FAILED:
23 return nil, NewSyscallError("WaitForSingleObject", e)
24 default:
25 return nil, errors.New("os: unexpected result from WaitForSingleObject")
26 }
27 var ec uint32
28 e = syscall.GetExitCodeProcess(syscall.Handle(handle), &ec)
29 if e != nil {
30 return nil, NewSyscallError("GetExitCodeProcess", e)
31 }
32 var u syscall.Rusage
33 e = syscall.GetProcessTimes(syscall.Handle(handle), &u.CreationTime, &u.ExitTime, &u.KernelTime, &u.UserTime)
34 if e != nil {
35 return nil, NewSyscallError("GetProcessTimes", e)
36 }
37 p.setDone()
38
39
40
41
42
43 defer time.Sleep(5 * time.Millisecond)
44 defer p.Release()
45 return &ProcessState{p.Pid, syscall.WaitStatus{ExitCode: ec}, &u}, nil
46 }
47
48 func (p *Process) signal(sig Signal) error {
49 handle := atomic.LoadUintptr(&p.handle)
50 if handle == uintptr(syscall.InvalidHandle) {
51 return syscall.EINVAL
52 }
53 if p.done() {
54 return ErrProcessDone
55 }
56 if sig == Kill {
57 var terminationHandle syscall.Handle
58 e := syscall.DuplicateHandle(^syscall.Handle(0), syscall.Handle(handle), ^syscall.Handle(0), &terminationHandle, syscall.PROCESS_TERMINATE, false, 0)
59 if e != nil {
60 return NewSyscallError("DuplicateHandle", e)
61 }
62 runtime.KeepAlive(p)
63 defer syscall.CloseHandle(terminationHandle)
64 e = syscall.TerminateProcess(syscall.Handle(terminationHandle), 1)
65 return NewSyscallError("TerminateProcess", e)
66 }
67
68 return syscall.Errno(syscall.EWINDOWS)
69 }
70
71 func (p *Process) release() error {
72 handle := atomic.SwapUintptr(&p.handle, uintptr(syscall.InvalidHandle))
73 if handle == uintptr(syscall.InvalidHandle) {
74 return syscall.EINVAL
75 }
76 e := syscall.CloseHandle(syscall.Handle(handle))
77 if e != nil {
78 return NewSyscallError("CloseHandle", e)
79 }
80
81 runtime.SetFinalizer(p, nil)
82 return nil
83 }
84
85 func findProcess(pid int) (p *Process, err error) {
86 const da = syscall.STANDARD_RIGHTS_READ |
87 syscall.PROCESS_QUERY_INFORMATION | syscall.SYNCHRONIZE
88 h, e := syscall.OpenProcess(da, false, uint32(pid))
89 if e != nil {
90 return nil, NewSyscallError("OpenProcess", e)
91 }
92 return newProcess(pid, uintptr(h)), nil
93 }
94
95 func init() {
96 cmd := windows.UTF16PtrToString(syscall.GetCommandLine())
97 if len(cmd) == 0 {
98 arg0, _ := Executable()
99 Args = []string{arg0}
100 } else {
101 Args = commandLineToArgv(cmd)
102 }
103 }
104
105
106 func appendBSBytes(b []byte, n int) []byte {
107 for ; n > 0; n-- {
108 b = append(b, '\\')
109 }
110 return b
111 }
112
113
114
115 func readNextArg(cmd string) (arg []byte, rest string) {
116 var b []byte
117 var inquote bool
118 var nslash int
119 for ; len(cmd) > 0; cmd = cmd[1:] {
120 c := cmd[0]
121 switch c {
122 case ' ', '\t':
123 if !inquote {
124 return appendBSBytes(b, nslash), cmd[1:]
125 }
126 case '"':
127 b = appendBSBytes(b, nslash/2)
128 if nslash%2 == 0 {
129
130
131
132 if inquote && len(cmd) > 1 && cmd[1] == '"' {
133 b = append(b, c)
134 cmd = cmd[1:]
135 }
136 inquote = !inquote
137 } else {
138 b = append(b, c)
139 }
140 nslash = 0
141 continue
142 case '\\':
143 nslash++
144 continue
145 }
146 b = appendBSBytes(b, nslash)
147 nslash = 0
148 b = append(b, c)
149 }
150 return appendBSBytes(b, nslash), ""
151 }
152
153
154
155
156 func commandLineToArgv(cmd string) []string {
157 var args []string
158 for len(cmd) > 0 {
159 if cmd[0] == ' ' || cmd[0] == '\t' {
160 cmd = cmd[1:]
161 continue
162 }
163 var arg []byte
164 arg, cmd = readNextArg(cmd)
165 args = append(args, string(arg))
166 }
167 return args
168 }
169
170 func ftToDuration(ft *syscall.Filetime) time.Duration {
171 n := int64(ft.HighDateTime)<<32 + int64(ft.LowDateTime)
172 return time.Duration(n*100) * time.Nanosecond
173 }
174
175 func (p *ProcessState) userTime() time.Duration {
176 return ftToDuration(&p.rusage.UserTime)
177 }
178
179 func (p *ProcessState) systemTime() time.Duration {
180 return ftToDuration(&p.rusage.KernelTime)
181 }
182
View as plain text