run, exec: fix -i hanging when stdin reaches EOF during task creation#5042
Merged
Conversation
`nerdctl (run|exec) -i` (without `-t`) propagates the EOF of its own stdin to the container by calling CloseIO: the shim deliberately keeps its own write end of the stdin FIFO open (so that a detached client does not propagate EOF), and only CloseIO makes the shim close it. The io copy goroutines are started by the cio.Creator, inside container.NewTask (respectively task.Exec), before the task (process) is registered in containerd: - in taskutil.NewTask, when the stdin was short enough to reach EOF during the creation, the container.Task API lookup in the closer failed with "no such task", and the error was discarded at the debug level; - in container.Exec, the closer was only installed after task.Exec returned, and a closer firing before that was a silent no-op. In both cases the CloseIO was lost forever: the container never received EOF on its stdin, and eg: `nerdctl run --rm -i IMAGE cat` hung until killed. Make the closer block on a channel that receives the task (process) handle when the creation returns, so that the CloseIO is always delivered. The race is easily reproducible under load; in the CI it is the cause of the TestRunStdin flakiness, which became a consistent failure on the slow almalinux-8 guests after the tests moved out of Docker. Fix issue 5029 Assisted-by: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
ktock
approved these changes
Jul 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
nerdctl (run|exec) -i(without-t) propagates the EOF of its own stdin to the container by calling CloseIO: the shim deliberately keeps its own write end of the stdin FIFO open (so that a detached client does not propagate EOF), and only CloseIO makes the shim close it.The io copy goroutines are started by the cio.Creator, inside container.NewTask (respectively task.Exec), before the task (process) is registered in containerd:
In both cases the CloseIO was lost forever: the container never received EOF on its stdin, and eg:
nerdctl run --rm -i IMAGE cathung until killed.Make the closer block on a channel that receives the task (process) handle when the creation returns, so that the CloseIO is always delivered.
The race is easily reproducible under load; in the CI it is the cause of the TestRunStdin flakiness, which became a consistent failure on the slow almalinux-8 guests after the tests moved out of Docker.
Fix #5029
Assisted-by: Claude Fable 5 noreply@anthropic.com