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 )
67 pid1, err := ignoringEINTR2(func() (int, error) {
68 return syscall.Wait4(p.Pid, &status, 0, &rusage)
69 })
70 if err != nil {
71 return nil, NewSyscallError("wait", err)
72 }
73 p.pidDeactivate(statusDone)
74 return &ProcessState{
75 pid: pid1,
76 status: status,
77 rusage: &rusage,
78 }, nil
79 }
80
81 func (p *Process) signal(sig Signal) error {
82 s, ok := sig.(syscall.Signal)
83 if !ok {
84 return errors.New("os: unsupported signal type")
85 }
86
87
88 switch p.mode {
89 case modeHandle:
90
91 return p.pidfdSendSignal(s)
92 case modePID:
93
94 return p.pidSignal(s)
95 default:
96 panic("unreachable")
97 }
98 }
99
100 func (p *Process) pidSignal(s syscall.Signal) error {
101 if p.Pid == pidReleased {
102 return errors.New("os: process already released")
103 }
104 if p.Pid == pidUnset {
105 return errors.New("os: process not initialized")
106 }
107
108 p.sigMu.RLock()
109 defer p.sigMu.RUnlock()
110
111 switch p.pidStatus() {
112 case statusDone:
113 return ErrProcessDone
114 case statusReleased:
115 return errors.New("os: process already released")
116 }
117
118 return convertESRCH(syscall.Kill(p.Pid, s))
119 }
120
121 func convertESRCH(err error) error {
122 if err == syscall.ESRCH {
123 return ErrProcessDone
124 }
125 return err
126 }
127
128 func (p *Process) release() error {
129
130
131
132 p.Pid = pidReleased
133
134 switch p.mode {
135 case modeHandle:
136
137
138
139
140
141 p.handlePersistentRelease(statusReleased)
142 case modePID:
143
144 p.pidDeactivate(statusReleased)
145 }
146
147 runtime.SetFinalizer(p, nil)
148 return nil
149 }
150
151 func findProcess(pid int) (p *Process, err error) {
152 h, err := pidfdFind(pid)
153 if err == ErrProcessDone {
154
155
156
157 return newDoneProcess(pid), nil
158 } else if err != nil {
159
160
161 return newPIDProcess(pid), nil
162 }
163
164 return newHandleProcess(pid, h), nil
165 }
166
167 func (p *ProcessState) userTime() time.Duration {
168 return time.Duration(p.rusage.Utime.Nano()) * time.Nanosecond
169 }
170
171 func (p *ProcessState) systemTime() time.Duration {
172 return time.Duration(p.rusage.Stime.Nano()) * time.Nanosecond
173 }
174
View as plain text