Skip to content
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

process: kill child on error while spawning #6803

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

Maki325
Copy link

@Maki325 Maki325 commented Aug 27, 2024

There's a chance that between spawning of the std Child, and wrapping
it into a tokio impl an error can occurs, which would leave the child
alive, with no way to access it from the user side and not being part
of the tokio runtime.

This commit fixes that issue by wrapping the std Child right after
spawning with a struct that implements Drop, where the child would
be killed if it's dropped.

Fixes: #6797

There's a chance that between spawning of the `std Child`, and wrapping
it into a tokio impl an error can occurs, which would leave the child
alive, with no way to access it from the user side and not being part
of the tokio runtime.

This commit fixes that issue by wrapping the `std Child` right after
spawning with a struct that implements Drop, where the child would
be killed if it's dropped.

Fixes: tokio-rs#6797
@Darksonn Darksonn requested a review from ipetkov August 28, 2024 07:44
@Darksonn Darksonn added A-tokio Area: The main tokio crate M-process Module: tokio/process labels Aug 28, 2024
@@ -115,21 +115,97 @@ impl fmt::Debug for Child {
}
}

pub(crate) struct ChildDropGuard {
Copy link
Member

Choose a reason for hiding this comment

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

We already define ChildDropGuard in tokio/src/process/mod.rs. Can we:

  • reuse that type instead of having to redefine it in the unix and windows modules?
  • re-structure how/where the StdChild is wrapped so we don't end up double wrapping?
    • as this PR is currently laid out we will end up having two kill-on-drop wrappers which will have different behavior (namely trying to kill the process twice which is different behavior than we have today)

Copy link
Author

Choose a reason for hiding this comment

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

We can maybe combine ChildDropGuard from tokio/src/process/unix/mod.rs and DroppableChild from tokio/src/process/windows.rs, and have it in tokio/src/process/mod.rs, but we cant use ChildDropGuard from tokio/src/process/mod.rs. The reason being that we want the ability to take the child out from the Wapper struct, and ChildDropGuard from tokio/src/process/mod.rs doesn't allow that. The reason being that implementing Drop doesn't allow destructuring, so in the other implementations we use Options to circumvent that.

The double wrapped child won't make the process be killed twice, as we set the inner wrapper(ChildDropGuard from tokio/src/process/unix/mod.rs) to not kill the child on drop (tokio/src/process/unix/mod.rs line 202), so only the outer one(ChildDropGuard from tokio/src/process/mod.rs) will do that if so set.

I tried to make it so there's no double wrapping, but I couldn't make the PidfdReaper::new impl work. Because I would have to some way extract the child from the wrapper in the new function. And I couldn't get it to work.

Copy link
Member

Choose a reason for hiding this comment

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

It is okay if the definition of ChildDropGuard needs to move out of tokio/src/process/mod.rs and into the platform-specific implementation modules, but there is no need to have two wrappers which attempt to perform a kill-on-drop (and bloat the data structures with redundant bools).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-tokio Area: The main tokio crate M-process Module: tokio/process
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Child process can be spawned even when tokio::process::Command::spawn returns an error
3 participants