X Tutup
Skip to content

Commit 6ee8577

Browse files
committed
sys/reaper: avoid leaky goroutine when exec timeout
The channel is created with no capacity that it needs receiver when sending data. Otherwise, the sending-data goroutine will be blocked forever. For the containerd#6166 pr, the exec command timeout will return and no receiver for the data. It will cause goroutine leaky. This commit allocates buffered channel for the command status and closes the channel after sending. And also use time.Timer with Stop for performance concern. Signed-off-by: Wei Fu <fuweid89@gmail.com>
1 parent d0bdb0b commit 6ee8577

File tree

1 file changed

+21
-11
lines changed

1 file changed

+21
-11
lines changed

sys/reaper/reaper_unix.go

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -119,23 +119,33 @@ func (m *Monitor) Wait(c *exec.Cmd, ec chan runc.Exit) (int, error) {
119119

120120
// WaitTimeout is used to skip the blocked command and kill the left process.
121121
func (m *Monitor) WaitTimeout(c *exec.Cmd, ec chan runc.Exit, timeout time.Duration) (int, error) {
122-
sch := make(chan int)
123-
ech := make(chan error)
122+
type exitStatusWrapper struct {
123+
status int
124+
err error
125+
}
126+
127+
// capacity can make sure that the following goroutine will not be
128+
// blocked if there is no receiver when timeout.
129+
waitCh := make(chan *exitStatusWrapper, 1)
124130
go func() {
131+
defer close(waitCh)
132+
125133
status, err := m.Wait(c, ec)
126-
sch <- status
127-
if err != nil {
128-
ech <- err
134+
waitCh <- &exitStatusWrapper{
135+
status: status,
136+
err: err,
129137
}
130138
}()
139+
140+
timer := time.NewTimer(timeout)
141+
defer timer.Stop()
142+
131143
select {
132-
case <-time.After(timeout):
144+
case <-timer.C:
133145
syscall.Kill(c.Process.Pid, syscall.SIGKILL)
134-
return 0, errors.Errorf("timeout %ds for cmd(pid=%d): %s, %s", timeout/time.Second, c.Process.Pid, c.Path, c.Args)
135-
case status := <-sch:
136-
return status, nil
137-
case err := <-ech:
138-
return -1, err
146+
return 0, errors.Errorf("timeout %v for cmd(pid=%d): %s, %s", timeout, c.Process.Pid, c.Path, c.Args)
147+
case res := <-waitCh:
148+
return res.status, res.err
139149
}
140150
}
141151

0 commit comments

Comments
 (0)
X Tutup