
On Wed, Nov 14, 2012 at 2:24 AM, Boris Schaeling <boris@highscore.de> wrote:
On Tue, 13 Nov 2012 23:42:08 +0100, Yakov Galka <ybungalobill@gmail.com> wrote:
[...]Now, consider the following execution order: A1, B1, A2, B2, A3, B3.
The
result is that the write-end of the pipe of b.exe is inherited by a.exe too (i.e. 'leaked' into a.exe). b.exe exits, closing its write-end of the pipe. However, a.exe still holds (indefinitely) the write-end of b's pipe! Result: thread B will hang until the unrelated process a.exe exits (and perhaps all the children that a.exe created in its own turn).
On Windows create_pipe() creates non-inheritable handles for the pipe. They only become inheritable when an initializer like bind_stdout is used. Do you think this solves the problem you outlined?
No, this is *not* enough. There is a race condition between SetHandleInformation and CreateProcess. That is, the code is essentially equivalent to: SetHandleInformation(h, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); // 1 CreateProcess(...) if during (1) you call to CreateProcess from another thread (with inheritHandles set to true) then h is leaked to that other process.
On POSIX one could use initializers like close_fds or close_fds_if to explicitly close file descriptors for child processes. Then no "leak" should be possible either.
I don't know whether that would be enough to turn Boost.Process into a thread-safe library (I didn't think about thread-safety yet). But then your example could be worth adding to the FAQ?
To my understanding on POSIX the situation is even worse, because by default you inherit *all* descriptors, except those that you explicitly mark to be closed. The API you need is basically the opposite: inherit none except those you really want. -- Yakov