Child processes always unwantedly inherit Handles on Windows
runInteractiveProcess (the one in
runProcess.c, not the Haskell one) calls
bInheritHandles set to
TRUE, but the whole thing is not wrapped in a critical section. Microsoft has a decent explanation of why this is a problem and I found that it's a two-year old unfixed bug in the Java runtime as well.
In case it's not obvious, the reason why we don't want Handles to be inherited is that then a child process may hang on to it well after it should have been closed. The end result is that trying to do anything to it results in a sharing violation. The case in which I originally ran into this was
System.Directory.copyFile intermittently reporting a "permission denied" error for a temp file it was using. I think it was trying to delete it, but failing because a child process somewhere was hanging on to the Handle.
Attached is code demonstrating the problem. It forks a thread which repeatedly tries to open and close the file
foo.tmp. The main thread then spawns processes as fast as it can until the other one fails to open the file. This, I think, cannot happen on non-Windows platforms since two processes can have the same file open without trouble. Do not run except on Windows, you risk flooding your system with
It may be sensible to make this controllable with the
close_fds parameter to
createProcess, which is currently just ignored on Windows. I can't see why anybody could ever want this behaviour, though.
I've tested only process-1.0.1 with it, and the
openFile fails reliably after spawning up to about 4 processes.