Repository navigation
Conversation
JobObjectChild kept its job's handle to itself, so only the holder of the child could end the job: not another thread while one waits on the child, and not anyone once the child is dropped. `job_handle()` returns a JobObjectHandle, which can be cloned and sent across threads, terminates the job without the child, and keeps the job open while it's held. The job is still closed once, when the child and its last handle are gone.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
JobObjectChildkeeps its job's handle to itself, so only whoever holds the child can end the job, withstart_kill()or by dropping it withKillOnDrop. That's a problem when someone else holds the child. We hit it in a desktop app where one thread owns a child process and waits on it, and another (quitting, or cleaning up the folder the child works in) has to end the child and everything it started.wait()takes&mut self, so the other thread can't callstart_kill(). We ended up writing our own job object code just to keep the handle: start suspended, create the job, assign the process, then find and resume its thread.JobObjectalready does all of that.The same goes for a caller that needs the job to outlive the child. With
KillOnDrop, the job's processes are killed as soon as the child is dropped.This adds
JobObjectChild::job_handle()to both the std and Tokio frontends. It returns aJobObjectHandle:Clone,SendandSync. Clones share the job's one handle through anArc.terminate(exit_code)callsTerminateJobObject, asstart_kill()does.AsHandle, so the job can be used with other job APIs without process-wrap wrapping each one or exposingwindowstypes.JobObjectHandlehave both been dropped, so no handle can refer to a closed job. Code that never takes a handle behaves as before, andinto_inner()still leaves the job open.Internally,
JobPortholds aJobObjectHandleinstead of a rawHANDLE, andterminate_job()is nowJobObjectHandle::terminate().The tests are in
tests/std_windows/job_handle.rsandtests/tokio_windows/job_handle.rs. Likejob_object_kill_on_drop.rs, they start the test binary as a parent that starts a child of its own and prints its PID. They check that:KillOnDrop, the descendant keeps running after the child is dropped while a handle is held, and is killed once the handle is dropped.I ran the Windows half of CI's matrix on Windows Server 2025: stable and 1.87.0,
stdandtokio1, with and without default features, all features, clippy, rustdoc and fmt. I also ran the new tests 20 times in a row.