Skip to content

Use async pid fd instead of blocking waitid to wait for a child process to exit #745

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Feb 25, 2025

Conversation

jprendes
Copy link
Collaborator

@jprendes jprendes commented Nov 22, 2024

This PR replaces the blocking waitid call with an async implementation based on pid fd.
There's a race condition where containerd-shim reaps child processes.
If the child process has already been reaped, query containerd-shim to get the process status.

Note that this race condition is already present in the current implementation, but runwasi's waitid is very likely to win the race, the introduction of async evens out the odds between runwasi and containerd-shim.

This PR is in preparation to move the whole shim implementation to async.

Copy link
Member

@andreiltd andreiltd left a comment

Choose a reason for hiding this comment

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

LGTM!

Mossaka
Mossaka previously approved these changes Nov 26, 2024
Copy link
Member

@Mossaka Mossaka left a comment

Choose a reason for hiding this comment

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

LGTM!

@jprendes
Copy link
Collaborator Author

I still need to figure out why CI is failing. I think the http_poxy container is not receiving the SiGINT for some reason. But I don't see how that can relate to this. I'll keep digging tomorrow.

@jprendes jprendes force-pushed the async-shim-v3 branch 3 times, most recently from 29927c0 to 4a4f9b0 Compare January 23, 2025 11:02
@jprendes jprendes changed the title Use async pid fd instead of blocking waitid to wait for a child process to exit Use containerd-shim monitor to wait for child to exit Jan 23, 2025
@jprendes jprendes force-pushed the async-shim-v3 branch 2 times, most recently from f29e21c to 26d8ab0 Compare January 23, 2025 14:50
@jprendes jprendes changed the title Use containerd-shim monitor to wait for child to exit Use async pid fd instead of blocking waitid to wait for a child process to exit Jan 23, 2025
@jprendes jprendes force-pushed the async-shim-v3 branch 3 times, most recently from 92edd5b to e89619a Compare January 23, 2025 16:02
@jprendes jprendes requested review from Mossaka and andreiltd January 23, 2025 16:25
Mossaka
Mossaka previously approved these changes Jan 27, 2025
Copy link
Member

@Mossaka Mossaka left a comment

Choose a reason for hiding this comment

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

Great! Thanks for working on this

What I'd like to see, perhaps as a follow up, is some unit tests for edge cases like

  1. What would happen if the pid does not exist
  2. what would happen if the orignal PID is reused by a new process after the first one exists.
  3. what would happen to call wait() when containerd-shim has already reaped the process

Copy link
Member

@Mossaka Mossaka left a comment

Choose a reason for hiding this comment

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

Great! Thanks for working on this

What I'd like to see, perhaps as a follow up, is some unit tests for edge cases like

  1. What would happen if the pid does not exist
  2. what would happen if the orignal PID is reused by a new process after the first one exists.
  3. what would happen to call wait() when containerd-shim has already reaped the process

@Mossaka
Copy link
Member

Mossaka commented Jan 27, 2025

Note that this race condition is already present in the current implementation, but runwasi's waitid is very likely to win the race, the introduction of async evens out the odds between runwasi and containerd-shim.

Just to clarify, in this PR, you did not resolve this issue, right? If yes, could you please raise an issue against the repo so that we can track this one.

Signed-off-by: Jorge Prendes <[email protected]>
@jprendes
Copy link
Collaborator Author

Just to clarify, in this PR, you did not resolve this issue, right?

It doesn't resolve the underlying race condition, but it covers all possible outcomes, so it's not an issue for runwasi.

could you please raise an issue against the repo so that we can track this one

To be fair, we could just use the containerd_shim reaper alone, and we wouldn't need the pidfd part.
I think that's how containerd_shim intendeds it to be used.
However, that breaks our tests, as we don't bootstrap the containerd_shim reaper in tests.
If we do bootstrap the containerd_shim reaper in tests, then we would break tests that use process::Command, as they would hit the same race condition.

@jprendes
Copy link
Collaborator Author

  1. What would happen if the pid does not exist

During wait, it would hit the ECHILD branch, and then wait forever in the c8d_shim reaper. Fixed it so that we wait with a timeout.

  1. what would happen if the orignal PID is reused by a new process after the first one exists.

That's not a problem.

  • PIDFD is resilient to that by using a dedicated FD instead of the PID.
  • The reaper should send the correct event regardless. Assuming the reaper always wins, that would mean that the reaper would broadcast two events with the same PID, but we stop listening after the first hit.
  1. what would happen to call wait() when containerd-shim has already reaped the process

As long as the struct is created before the process exits, that's not a problem. That's why we create the struct BEFORE calling container.start(). I added a comment explaining this in the code.

Mossaka
Mossaka previously approved these changes Feb 25, 2025
Copy link
Member

@Mossaka Mossaka left a comment

Choose a reason for hiding this comment

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

LGTM!

@jprendes jprendes dismissed Mossaka’s stale review February 25, 2025 23:43

The merge-base changed after approval.

@Mossaka Mossaka merged commit 99ea2d2 into containerd:main Feb 25, 2025
75 checks passed
@jprendes jprendes deleted the async-shim-v3 branch February 27, 2025 10:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants