From ae65491223a460b0a902993ac81ac91ca69c91fa Mon Sep 17 00:00:00 2001 From: Ophestra Date: Wed, 15 Oct 2025 21:35:19 +0900 Subject: container/init: use one channel for wait4 When using two channels it is possible for the other case to be reached before all pending winfo are consumed, causing incorrect reporting. Signed-off-by: Ophestra --- container/init.go | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'container/init.go') diff --git a/container/init.go b/container/init.go index ff72c403..e38127fd 100644 --- a/container/init.go +++ b/container/init.go @@ -353,10 +353,14 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) { wpid int wstatus WaitStatus } + + // info is closed as the wait4 thread terminates + // when there are no longer any processes left to reap info := make(chan winfo, 1) - done := make(chan struct{}) k.new(func(k syscallDispatcher) { + k.lockOSThread() + var ( err error wpid = -2 @@ -382,7 +386,7 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) { k.printf(msg, "unexpected wait4 response: %v", err) } - close(done) + close(info) }) // handle signals to dump withheld messages @@ -411,7 +415,13 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) { msg.BeforeExit() k.exit(0) - case w := <-info: + case w, ok := <-info: + if !ok { + msg.BeforeExit() + k.exit(r) + continue // unreachable + } + if w.wpid == cmd.Process.Pid { // initial process exited, output is most likely available again msg.Resume() @@ -433,10 +443,6 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) { go func() { time.Sleep(params.AdoptWaitDelay); close(timeout) }() } - case <-done: - msg.BeforeExit() - k.exit(r) - case <-timeout: k.printf(msg, "timeout exceeded waiting for lingering processes") msg.BeforeExit() -- cgit v1.3.1