Avoid race codition when setting process exit code on Windows.
authorJan Dubois <jand@activestate.com>
Fri, 11 Mar 2011 18:30:11 +0000 (10:30 -0800)
committerJan Dubois <jand@activestate.com>
Fri, 11 Mar 2011 18:30:11 +0000 (10:30 -0800)
A Perl program using fork() emulation on Windows may end up
kill()ing the forked child and exiting immediately.  There
is a race condition where the process exit code may be
changed to '9' (the signal used to kill the child thread),
overriding the value the parent thread used in ExitProcess()
(called implicitly with the return value of main()).

Giving up the remainder of the time-slice after terminating
a child thread seems to eliminate this race.

This bug is responsible for various CPAN test failures,
where all tests seem to pass, but Test::Harness still
reports: "Dubious, test returned 9 (wstat 2304, 0x900)"
(e.g. HTTP-Server-Simple, tests based on Test-TCP).

See also https://rt.cpan.org/Ticket/Display.html?id=66016#txn-908976

t/op/fork.t
win32/win32.c

index 3c40394..b8c03ab 100644 (file)
@@ -452,3 +452,15 @@ EXPECT
 OPTION random
 child: called as [main::f(foo,bar)]
 waitpid() returned ok
+########
+# Windows 2000: https://rt.cpan.org/Ticket/Display.html?id=66016#txn-908976
+system $^X,  "-e", "if (\$pid=fork){sleep 1;kill(9, \$pid)} else {sleep 5}";
+print $?>>8, "\n";
+EXPECT
+0
+########
+# Windows 7: https://rt.cpan.org/Ticket/Display.html?id=66016#txn-908976
+system $^X,  "-e", "if (\$pid=fork){kill(9, \$pid)} else {sleep 5}";
+print $?>>8, "\n";
+EXPECT
+0
index 019e681..2394524 100644 (file)
@@ -1282,6 +1282,13 @@ win32_kill(int pid, int sig)
            case 9:
                 /* kill -9 style un-graceful exit */
                if (TerminateThread(hProcess, sig)) {
+                    /* Allow the scheduler to finish cleaning up the other thread.
+                     * Otherwise, if we ExitProcess() before another context switch
+                     * happens we will end up with a process exit code of "sig" instead
+                     * of our own exit status.
+                     * See also: https://rt.cpan.org/Ticket/Display.html?id=66016#txn-908976
+                     */
+                    Sleep(0);
                    remove_dead_pseudo_process(child);
                    return 0;
                }