Description
The current implementation of the use_process_jobs
codepath on Windows (introduced in #80) has a few issues, the most significant of which can result in the process being unexpectedly terminated. Specifically, this issue can occur as follows:
- the user spawns a process with
use_process_jobs=True
- the user waits on the
ProcessHandle
withwaitForProcess
but holds no other reference to theProcessHandle
waitForProcess
safe-foreign-calls intowaitForJobCompletion
waitForJobCompletion
blocks withGetQueuedCompletionStatus
on the IOCP associated with the job- a major GC occurs, the
ProcessHandle
is collected since there are no references to it - the finalizer attached to the
ProcessHandle
'sMVar
is run, closing the process handles waitForJobCompletion
is unblocked by some event, handles it, and tries blocking againGetQueuedCompletionStatus
fails with an "invalid handle" error since the handle has been closedwaitForJobCompletion
sees the failure, breaks out of the loop, and returns with status code 0.- the caller thinks that the process finished successfully and is later surprised when this isn't the case
The reason this happens is that the use_process_jobs
codepath, unlike the other codepaths of waitForProcess
, makes no attempt to do anything with the process handle (e.g. updating the MVar
to be a ClosedHandle
) after it finishes waiting.
In addition, the use_process_jobs
codepath fails to call endDelegateControlC
on process completion, unlike the "normal" codepath.
As an orthogonal matter, the documentation of use_process_jobs
could be better; currently we don't adequately explain when a user should be using a job. In addition, we should note that exit codes may be incorrect on Windows when exec
is used.