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 with waitForProcess but holds no other reference to the ProcessHandle
waitForProcess safe-foreign-calls into waitForJobCompletion
waitForJobCompletion blocks with GetQueuedCompletionStatus 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's MVar is run, closing the process handles
waitForJobCompletion is unblocked by some event, handles it, and tries blocking again
GetQueuedCompletionStatus fails with an "invalid handle" error since the handle has been closed
waitForJobCompletion 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.
The current implementation of the
use_process_jobscodepath 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:use_process_jobs=TrueProcessHandlewithwaitForProcessbut holds no other reference to theProcessHandlewaitForProcesssafe-foreign-calls intowaitForJobCompletionwaitForJobCompletionblocks withGetQueuedCompletionStatuson the IOCP associated with the jobProcessHandleis collected since there are no references to itProcessHandle'sMVaris run, closing the process handleswaitForJobCompletionis unblocked by some event, handles it, and tries blocking againGetQueuedCompletionStatusfails with an "invalid handle" error since the handle has been closedwaitForJobCompletionsees the failure, breaks out of the loop, and returns with status code 0.The reason this happens is that the
use_process_jobscodepath, unlike the other codepaths ofwaitForProcess, makes no attempt to do anything with the process handle (e.g. updating theMVarto be aClosedHandle) after it finishes waiting.In addition, the
use_process_jobscodepath fails to callendDelegateControlCon process completion, unlike the "normal" codepath.As an orthogonal matter, the documentation of
use_process_jobscould 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 whenexecis used.