@@ -553,6 +553,38 @@ createCompletionPort (HANDLE hJob)
553
553
return ioPort ;
554
554
}
555
555
556
+ /* Note [Windows exec interaction]
557
+
558
+ The basic issue that process jobs tried to solve is this:
559
+
560
+ Say you have two programs A and B. Now A calls B. There are two ways to do this.
561
+
562
+ 1) You can use the normal CreateProcess API, which is what normal Windows code do.
563
+ Using this approach, the current waitForProcess works absolutely fine.
564
+ 2) You can call the emulated POSIX function _exec, which of course is supposed to
565
+ allow the child process to replace the parent.
566
+
567
+ With approach 2) waitForProcess falls apart because the Win32's process model does
568
+ not allow this the same way as linux. _exec is emulated by first making a call to
569
+ CreateProcess to spawn B and then immediately exiting from A. So you have two
570
+ different processes.
571
+
572
+ waitForProcess is waiting on the termination of A. Because A is immediately killed,
573
+ waitForProcess will return even though B is still running. This is why for instance
574
+ the GHC testsuite on Windows had lots of file locked errors.
575
+
576
+ This approach creates a new Job and assigned A to the job, but also all future
577
+ processes spawned by A. This allows us to listen in on events, such as, when all
578
+ processes in the job are finished, but also allows us to propagate exit codes from
579
+ _exec calls.
580
+
581
+ The only reason we need this at all is because we don't interact with just actual
582
+ native code on Windows, and instead have a lot of ported POSIX code.
583
+
584
+ The Job handle is returned to the user because Jobs have additional benefits as well,
585
+ such as allowing you to specify resource limits on the to be spawned process.
586
+ */
587
+
556
588
ProcHandle
557
589
runInteractiveProcess (wchar_t * cmd , wchar_t * workingDirectory ,
558
590
wchar_t * environment ,
@@ -668,8 +700,9 @@ runInteractiveProcess (wchar_t *cmd, wchar_t *workingDirectory,
668
700
dwFlags |= CREATE_NEW_CONSOLE ;
669
701
}
670
702
671
- // If we're going to use a job object, then we have to create
672
- // the thread suspended.
703
+ /* If we're going to use a job object, then we have to create
704
+ the thread suspended.
705
+ See Note [Windows exec interaction]. */
673
706
if (useJobObject )
674
707
{
675
708
dwFlags |= CREATE_SUSPENDED ;
0 commit comments