Source file
src/os/exec_unix.go
1
2
3
4
5
6
7 package os
8
9 import (
10 "errors"
11 "runtime"
12 "syscall"
13 "time"
14 )
15
16 const (
17
18 pidUnset = 0
19 pidReleased = -1
20 )
21
22 func (p *Process) wait() (ps *ProcessState, err error) {
23
24 switch p.mode {
25 case modeHandle:
26
27 return p.pidfdWait()
28 case modePID:
29
30 return p.pidWait()
31 default:
32 panic("unreachable")
33 }
34 }
35
36 func (p *Process) pidWait() (*ProcessState, error) {
37
38
39
40
41
42
43 switch p.pidStatus() {
44 case statusReleased:
45 return nil, syscall.EINVAL
46 }
47
48
49 ready, err := p.blockUntilWaitable()
50 if err != nil {
51 return nil, err
52 }
53 if ready {
54
55
56 p.pidDeactivate(statusDone)
57
58
59 p.sigMu.Lock()
60 p.sigMu.Unlock()
61 }
62
63 var (
64 status syscall.WaitStatus
65 rusage syscall.Rusage
66 pid1 int
67 e error
68 )
69 for {
70 pid1, e = syscall.Wait4(p.Pid, &status, 0, &rusage)
71 if e != syscall.EINTR {
72 break
73 }
74 }
75 if e != nil {
76 return nil, NewSyscallError("wait", e)
77 }
78 p.pidDeactivate(statusDone)
79 return &ProcessState{
80 pid: pid1,
81 status: status,
82 rusage: &rusage,
83 }, nil
84 }
85
86 func (p *Process) signal(sig Signal) error {
87 s, ok := sig.(syscall.Signal)
88 if !ok {
89 return errors.New("os: unsupported signal type")
90 }
91
92
93 switch p.mode {
94 case modeHandle:
95
96 return p.pidfdSendSignal(s)
97 case modePID:
98
99 return p.pidSignal(s)
100 default:
101 panic("unreachable")
102 }
103 }
104
105 func (p *Process) pidSignal(s syscall.Signal) error {
106 if p.Pid == pidReleased {
107 return errors.New("os: process already released")
108 }
109 if p.Pid == pidUnset {
110 return errors.New("os: process not initialized")
111 }
112
113 p.sigMu.RLock()
114 defer p.sigMu.RUnlock()
115
116 switch p.pidStatus() {
117 case statusDone:
118 return ErrProcessDone
119 case statusReleased:
120 return errors.New("os: process already released")
121 }
122
123 return convertESRCH(syscall.Kill(p.Pid, s))
124 }
125
126 func convertESRCH(err error) error {
127 if err == syscall.ESRCH {
128 return ErrProcessDone
129 }
130 return err
131 }
132
133 func (p *Process) release() error {
134
135
136
137 p.Pid = pidReleased
138
139 switch p.mode {
140 case modeHandle:
141
142
143
144
145
146 p.handlePersistentRelease(statusReleased)
147 case modePID:
148
149 p.pidDeactivate(statusReleased)
150 }
151
152 runtime.SetFinalizer(p, nil)
153 return nil
154 }
155
156 func findProcess(pid int) (p *Process, err error) {
157 h, err := pidfdFind(pid)
158 if err == ErrProcessDone {
159
160
161
162 return newDoneProcess(pid), nil
163 } else if err != nil {
164
165
166 return newPIDProcess(pid), nil
167 }
168
169 return newHandleProcess(pid, h), nil
170 }
171
172 func (p *ProcessState) userTime() time.Duration {
173 return time.Duration(p.rusage.Utime.Nano()) * time.Nanosecond
174 }
175
176 func (p *ProcessState) systemTime() time.Duration {
177 return time.Duration(p.rusage.Stime.Nano()) * time.Nanosecond
178 }
179
View as plain text