Skip to content

Commit 5662c7f

Browse files
committed
feat: add an equivalent of WaitWrapper for os.Process
For using os.Process in Talos replacing exec.Cmd in some places we need to ba able to use reaper with it. Signed-off-by: Dmitry Sharshakov <[email protected]>
1 parent 71fced6 commit 5662c7f

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

Diff for: pkg/cmd/proc/reaper/reaper_test.go

+55
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,61 @@ func (suite *ReaperSuite) TestWait() {
188188
}
189189
}
190190

191+
func (suite *ReaperSuite) TestProcessWait() {
192+
type args struct {
193+
name string
194+
args []string
195+
}
196+
197+
tests := []struct { //nolint:govet
198+
args args
199+
errString string
200+
}{
201+
{
202+
args{
203+
"true",
204+
[]string{},
205+
},
206+
"",
207+
},
208+
{
209+
args{
210+
"false",
211+
[]string{},
212+
},
213+
"exit status 1",
214+
},
215+
{
216+
args{
217+
"/bin/sh",
218+
[]string{
219+
"-c",
220+
"kill -2 $$",
221+
},
222+
},
223+
"signal: interrupt",
224+
},
225+
}
226+
227+
notifyCh := make(chan reaper.ProcessInfo, 1)
228+
229+
suite.Require().True(reaper.Notify(notifyCh))
230+
defer reaper.Stop(notifyCh)
231+
232+
for _, t := range tests {
233+
cmd := exec.Command(t.args.name, t.args.args...)
234+
suite.Require().NoError(cmd.Start())
235+
236+
err := reaper.ProcessWaitWrapper(true, notifyCh, cmd.Process)
237+
238+
if t.errString == "" {
239+
suite.Assert().NoError(err)
240+
} else {
241+
suite.Assert().EqualError(err, t.errString)
242+
}
243+
}
244+
}
245+
191246
func TestReaperSuite(t *testing.T) {
192247
suite.Run(t, new(ReaperSuite))
193248
}

Diff for: pkg/cmd/proc/reaper/wait.go

+31
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package reaper
66

77
import (
88
"fmt"
9+
"os"
910
"os/exec"
1011
"syscall"
1112
)
@@ -37,6 +38,36 @@ func WaitWrapper(usingReaper bool, notifyCh <-chan ProcessInfo, cmd *exec.Cmd) e
3738
return err
3839
}
3940

41+
// ProcessWaitWrapper emulates os/exec.Process.Wait() when reaper is running.
42+
// It is equivalent to WaitWrapper
43+
//
44+
// ProcessWaitWrapper(true, proc) should be equivalent to proc.Wait().
45+
func ProcessWaitWrapper(usingReaper bool, notifyCh <-chan ProcessInfo, proc *os.Process) error {
46+
if !usingReaper {
47+
_, waitErr := proc.Wait()
48+
49+
return waitErr
50+
}
51+
52+
var info ProcessInfo
53+
54+
for info = range notifyCh {
55+
if info.Pid == proc.Pid && (info.Status.Exited() || info.Status.Signaled()) {
56+
break
57+
}
58+
}
59+
60+
err := convertWaitStatus(info.Status)
61+
62+
// release any resources
63+
waitErr := proc.Release()
64+
if err == nil && waitErr != nil && waitErr.Error() != "waitid: no child processes" {
65+
err = waitErr
66+
}
67+
68+
return err
69+
}
70+
4071
// ExitError is raised when exit status is not equal to 0.
4172
type ExitError struct {
4273
ExitCode int

0 commit comments

Comments
 (0)