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