-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Feat(process): Implement Command::spawn_with
#7249
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
Conversation
cc @ipetkov |
68dc83d
to
b04752a
Compare
Command::spawn_with
b04752a
to
4f793fe
Compare
29f509c
to
1f28c27
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall the changes seem sensible! Just have a few minor comments around cutting down unnecessary monomorphization
1f28c27
to
897ffbf
Compare
Something like this? |
92f4e92
to
c937c35
Compare
c937c35
to
0801c11
Compare
f0346e3
to
2701079
Compare
Command::spawn_with
Command::spawn_with
That's weird. The FreeBSD 64-bit run failed with this:
This is not a known spurious failure. I'm filing a bug ... |
Yeah, I had the same reaction 😅 I triggered a new pipeline since I could not find a way to restart the Cirrus job through GH, so we will see. It ended up succeeding, so it does seem like a spurious failure indeed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Just one nit.
See tokio-rs#7238. Signed-off-by: Paul Mabileau <[email protected]>
2701079
to
c2b8925
Compare
I noticed that github will set the resulting commit to be authored by |
Ah yes, I didn't know I had this inconsistency. I now disabled this proxying, so it should be better? |
Now it wants to use your hotmail rather than the harfanglab.fr address you put in the SoB. |
Eh, whatever, fine by me 🤷 |
Thanks for the PR! |
Many thanks! |
Bumps tokio from 1.44.2 to 1.45.0. Release notes Sourced from tokio's releases. Tokio v1.45.0 Added metrics: stabilize worker_total_busy_duration, worker_park_count, and worker_unpark_count (#6899, #7276) process: add Command::spawn_with (#7249) Changed io: do not require Unpin for some trait impls (#7204) rt: mark runtime::Handle as unwind safe (#7230) time: revert internal sharding implementation (#7226) Unstable rt: remove alt multi-threaded runtime (#7275) #6899: tokio-rs/tokio#6899 #7276: tokio-rs/tokio#7276 #7249: tokio-rs/tokio#7249 #7204: tokio-rs/tokio#7204 #7230: tokio-rs/tokio#7230 #7226: tokio-rs/tokio#7226 #7275: tokio-rs/tokio#7275 Commits 00754c8 chore: prepare Tokio v1.45.0 (#7308) 1ae9434 time: revert "use sharding for timer implementation" related changes (#7226) 8895bba ci: Test AArch64 Windows (#7288) 48ca254 time: update sleep documentation to reflect maximum allowed duration (#7302) a0af02a compat: add more documentation to tokio_util::compat (#7279) 0ce3a11 metrics: stabilize worker_park_count and worker_unpark_count (#7276) 1ea9ce1 ci: fix cfg!(miri) declarations in tests (#7286) 4d4d126 chore: prepare tokio-util v0.7.15 (#7283) 5490267 fs: update the mockall dev dependency to 0.13.0 (#7234) 1434b32 examples: improve echo example consistency (#7256) Additional commits viewable in compare view Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase. Dependabot commands and options You can trigger Dependabot actions by commenting on this PR: @dependabot rebase will rebase this PR @dependabot recreate will recreate this PR, overwriting any edits that have been made to it @dependabot merge will merge this PR after your CI passes on it @dependabot squash and merge will squash and merge this PR after your CI passes on it @dependabot cancel merge will cancel a previously requested merge and block automerging @dependabot reopen will reopen this PR if it is closed @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
This is very useful, thank you! |
This was added as unstable as a temporary measure until stdlib stabilizes |
@Darksonn I had a different use case for this: I wanted to take the stdout/stderr of a child and pipe it to another command like the example here: https://doc.rust-lang.org/std/process/struct.Stdio.html#impl-From%3CChildStdout%3E-for-Stdio (Maybe there's another way to do it other than my approach below, please let me know) I could take it from #[tokio::main]
async fn main() {
let hello = Command::new("echo")
.arg("Hello, world!")
.stdout(Stdio::piped())
.spawn() // converted to nonblocking io here
.expect("failed echo command");
let std_io: Result<Stdio, _> = hello.stdout.unwrap().try_into(); // extra try_into() and unwrap() compared to the std example
let reverse = Command::new("rev")
.stdin(std_io.unwrap())
.output().await.unwrap();
// works, but not ideal
assert_eq!(reverse.stdout, b"!dlrow ,olleH\n");
} What I really want to do: let mut std_io: Option<Stdio> = None;
let hello = Command::new("echo")
.arg("Hello, world!")
.stdout(Stdio::piped())
.spawn_with(|cmd| {
let mut child = cmd.spawn()?;
std_io = child.stdout.take().map(Stdio::from); // take control of the stdout handle
// ^ does not compile due to being inside Fn closure
Ok(child)
})
.expect("failed echo command");
let reverse = Command::new("rev")
.stdin(std_io.take().unwrap()) // put it in directly without converting it to non-blocking
.output().await.unwrap();
assert_eq!(reverse.stdout, b"!dlrow ,olleH\n"); Note that this doesn't compile and currently has to be worked around with |
If you have change requests, then please file a new issue. As for upgrading the closure to |
Motivation
#7238: under Windows, the spawn sometimes has to be configured in a specific way in order to achieve a specific behavior or to stay compatible with some other API. In our case, it is about spawning child processes as PPL when the parent (Rust) process currently runs as PPL.
In the standard library, it is currently supported through the nightly-only
windows_process_extensions_raw_attribute
feature. It was previously implemented by configuring theCommand
object using itsraw_attribute
extension method and then the regularspawn
added the attributes on the Windows process when appropriate. This meant that simply creating and configuring astd::process::Command
object was sufficient to spawn Tokio processes since there isimpl From<std::process:Command> for tokio::process::Command
.However, the unstable API has recently been changed and the attribute setting must now be explicitly performed at spawn time through a separate spawning method:
Command::spawn_with_attributes
. This means that the previous solution does not work anymore.Solution
Since nightly APIs cannot currently be consumed from Tokio in any way, including when put behind some sort of cfg gate such as
tokio_unstable
, this proposes to add a broader API that enables customizing what is used in order to actually perform the synchronous process spawn while letting the rest stay as is.This makes for a relatively small change and straightforward API addition. In particular, it allows keeping the nightly-only code outside of Tokio and more generally any kind of desired spawn customization, although not strictly necessary for the initial use case.
However, it could be considered too vague for such a niche use case while it could be replaced with a more specific
spawn_with_attributes
when the upstream feature is stabilized, even though it could take a long time, but this is the best comprise found for now. This is why the linked issue is not marked here as to be closed: it circumvents the problem at hand, but does not more directly solve it.Testing
No tests covering the new API have been added. Indeed, the standard library's side has landed a bit too recently (rust-lang/rust#123604, 1.85) it seems compared to the nightly distribution seen in CI so the Windows-specific part could be tested, while there does not seem to be nightly-only tests yet either. Also, considering the current
spawn
API has been internally rewritten in terms similar tospawn_with
's, the current tests should already cover this adequately.