Skip to content

libct: simplify exec fifo wait using poll(2)#5271

Open
captainmo1 wants to merge 1 commit into
opencontainers:mainfrom
captainmo1:5251-simplify-exec-fifo-wait
Open

libct: simplify exec fifo wait using poll(2)#5271
captainmo1 wants to merge 1 commit into
opencontainers:mainfrom
captainmo1:5251-simplify-exec-fifo-wait

Conversation

@captainmo1
Copy link
Copy Markdown

Replace the goroutine + channel + 100ms time.After + blocking-open in handleFifo with a poll(2) loop on a non-blocking-open. Use pidfd_open(2) where available to wait for init exit without timeout, falling back to /proc state checks with 100ms timeout on older kernels. Allowing us to wait on both write to execfifo and state of init process simultaneously.

Fixes #5251

@captainmo1 captainmo1 force-pushed the 5251-simplify-exec-fifo-wait branch 2 times, most recently from e91e67c to 1889c08 Compare May 11, 2026 20:37
// or the init process has exited. It does not consume the data — it only
// returns once a subsequent read on f will not block indefinitely.
func waitForFifoReady(f *os.File, pid int) error {
pidFd, err := unix.PidfdOpen(pid, 0)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use https://pkg.go.dev/os#Process.WithHandle here:

proc, _ := os.FindProcess(pid) // or add process() to parentProcess interface
var readyErr error
err := proc.WithHandle(func(pidfd uintptr) {
   readyErr = waitForReadyPidfd(f, int(pidfd))
})
if err != nil { // pidfd not supported
   return waitForFifoReadyPolling(f, pid)
}

This works better because WithHandle will only call the function if pidfd is fully supported by the kernel (there are many kernels with different nuances and you can rely on the Go runtime check).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree its much better

Copy link
Copy Markdown
Author

@captainmo1 captainmo1 May 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

os.Process.WithHandle became available in Go 1.26 but runc's go.mod is currently at go 1.25.0. We'll need to bump the version or I can continue using raw unix.PidfOpen for now.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a // TODO: switch to os.Process.WithHandle once go < 1.26 is no longer supported. or somesuch.

Comment thread libcontainer/container_linux.go
Copy link
Copy Markdown
Contributor

@kolyshkin kolyshkin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this! Left a few comments, but overall this looks good.

@KhurshidMurotov
Copy link
Copy Markdown

this is nice one

@captainmo1 captainmo1 force-pushed the 5251-simplify-exec-fifo-wait branch 3 times, most recently from 73c4cd4 to 460ea7f Compare May 19, 2026 15:28
Replace the goroutine + channel + 100ms time.After + blocking open
in handleFifo with a poll(2) loop on a non-blocking open. Use
pidfd_open(2) where available to wait for init exit without timeout,
falling back to /proc state checks with 100ms timeout on older
kernels.

Fixes opencontainers#5251

Signed-off-by: Mohammed Aminu Futa <mohammedfuta2000@gmail.com>
@captainmo1 captainmo1 force-pushed the 5251-simplify-exec-fifo-wait branch from 460ea7f to 72a9bd5 Compare May 22, 2026 22:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

exec.fifo handling is way too complicated

3 participants