-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
[cargo run] Should proxy signals to child process #2343
Comments
/cc me |
―@alexchriton in watchexec/cargo-watch#25 (comment) |
I was wondering how programs hook into their shutdown on Windows. On Unix, the polite thing to do is to SIGTERM (or SIGINT) processes, because SIGTERM is trappable so you can do stuff like closing sockets, releasing ports, and saying goodbye instead of just ceasing to exist. Does Windows have similar capabilities? |
Thanks for the report @passcod! Here's some thoughts of mine:
So overall, my recommendation would be something along the lines of:
Does that all make sense? |
One point about job objects on Windows which makes me a little uneasy is:
Which to me means two things:
|
Is there an equivalent of |
At least with respect to cargo-watch. |
If there is I'm at least unaware of such a piece of functionality which is standard. Which is to say that I don't believe it exists. |
For Unix, cargo watch will definitely use process groups, even though it might just become irrelevant if cargo goes to use For Windows, I'll have to investigate/think a bit more. I probably do not want to forgo support for Windows < 8 in cargo-watch. |
I've seen very weird behavior on OSX, where ctrl-cing a cargo run will sometimes kill the running process and sometimes leave it alive reparented to init. It's not totally clear to me what the conditions are that cause the behavior to change. |
Cargo doesn't itself manage child processes at all, so any weird behavior is likely just a relic of whatever the shell is doing. If a child process manually goes into a new group then when the shell kills the entire process group the child keeps going (as it's part of a different group). |
Currently it's somewhat surprising if you're using cargo and it's then ctrl-c'd. The child processes that Cargo spawned are likely to still be running around in the background as they're not killed as well, and this could cause output spew or future build failures. This situation is handled by default on Unix because ctrl-c will end up sending a signal to the entire *process group*, which kills everything, but on Windows we're not as lucky (just Cargo itself is killed). By using job objects on Windows we can ensure that the entire tree dies instead of just the top Cargo process. cc rust-lang#2343
Currently it's somewhat surprising if you're using cargo and it's then ctrl-c'd. The child processes that Cargo spawned are likely to still be running around in the background as they're not killed as well, and this could cause output spew or future build failures. This situation is handled by default on Unix because ctrl-c will end up sending a signal to the entire *process group*, which kills everything, but on Windows we're not as lucky (just Cargo itself is killed). By using job objects on Windows we can ensure that the entire tree dies instead of just the top Cargo process. cc #2343
Cargo now uses job objects on Windows, so I think the only change still needed here is to use |
|
It is indeed! This can probably only be used for |
I'm looking at Cargo's But as you said, other usages should not do a |
I've opted for the second for now, as there's more code that uses "exec" (e.g. |
Ah yeah adding a new |
Before, we would spawn a child process for the program. One of the problems with that is when killing the cargo process, the program continues running. With this change, the cargo process is replaced by the program, and killing it works.
Use CommandExt::exec for `cargo run` on Unix (#2343) Before, we would spawn a child process for the program. One of the problems with that is when killing the cargo process, the program continues running. With this change, the cargo process is replaced by the program, and killing it works. Before (`cargo run` is the parent): > 502 7615 7614 0 2:26PM ttys012 0:00.12 /Users/rstocker/.multirust/toolchains/stable-x86_64-apple-darwin/bin/cargo run > 502 7620 7615 0 2:26PM ttys012 0:00.01 target/debug/program After (the shell is the parent): > 502 81649 81648 0 5:27PM ttys012 0:00.69 -zsh > 502 7739 81649 0 2:26PM ttys012 0:01.27 target/debug/program
Is this issue solved by the previous commits? |
Indeed! |
I imagine it will not be available until a few weeks? |
This is likely already in the nightly Cargo builds, but yeah to get to stable it'll take awhile. |
From watchexec/cargo-watch#25, around this comment.
Also referring this short IRC conversation.
Background: Cargo Watch has improved behaviour when watching a Cargo project and running
cargo run
: on changes, it kills the childcargo run
process and starts a new one. This is highly helpful when developing web servers and other applications which never return. For prior art, see nodemon.Cargo Watch currently uses the stdlib's
Child#kill()
method on Windows, andlibc::kill()
on all other platforms (Unix), with a signal of 15 (SIGTERM).Problem:
cargo run
creates a new child process. Killing thecargo run
child does not kill the grand-child. Cargo Watch then proceeds to start a newcargo-run
process, which attempts to start a new grand-child. We now have two of the target process, which is obviously unexpected and wrong. In the case of webservers, the first target process is still bound to its TCP port, preventing latter target processes from functioning, producing EADDRINUSE errors.Proposal: To have
cargo run
proxy signals to its own child process, allowing Cargo Watch (and other applications openingcargo
child commands) to send a SIGTERM (on Unix) or taskkill (on Windows, through the stdlib's implementation) directly to the target process. The target would then be responsible for its own shutdown.Cargo Watch would not attempt to send further signals, instead waiting for the
cargo run
process to return normally.cargo-run
may want to SIGKILL its child if it does not seem to be responding to SIGTERM, but I will leave that up to Cargo maintainers.I am also not familiar with the behaviours on Windows, so cannot comment on that aspect.
The text was updated successfully, but these errors were encountered: