GSubprocess behaviour on Windows is suboptimal in several aspects
I previously discussed this shortly with @icq so let's CC him here. Also @fanc999, @creiter, @nirbheek.
I recently wrote a helper process that is spawned via GSubprocess
and communicates with the main process with stdin/stdout. Nothing special there on Linux, however on Windows there are a couple of papercuts that makes hard to use and made me question whether I should simply not use GSubprocess
on Windows for this purpose but instead directly use Windows API (like the helper process does already for similar reasons).
The main problems here are the way how the stdin/stdout pipes work, namely
GSubprocess
creates a non-overlapped, bidirectional pipe for the subprocess stdin/out
On Windows the stdin/stdout pipes are created via _pipe()
, which is UNIX compat API. This creates a bi-directional, unnamed, non-overlapped pipe.
This means that the subprocess can't use overlapped IO (basically "non-blocking IO" on UNIX but a bit different) to asynchronously handle reads from the stdin pipe, or writes to the stdout pipe.
It also means that WaitForMultipleObjects()
and friends can't be used on the pipe to wait until the read (stdin) or write (stdout) condition happens, as both pipes are bidirectional and WaitForMultipleObjects()
does not distinguish between the direction. I.e. stdin is always "ready" because writing a byte to it would not block.
In essence the only way to handle stdin asynchronously in the subprocess is to go via a helper thread just for this purpose, which seems rather suboptimal.
GSubprocess
uses a blocking pipe for communicating with the subprocess, requiring a separate thread
On the main process side, there's a similar problem. The only way to read asynchronously from the stdout pipe or to write asynchronously to the stdin pipe is via a thread pool, which the corresponding GIO operations already do.
This is inefficient and unnecessary. If the first item was solved, then this could be solved by e.g. using overlapped IO in the main process too.
Which brings me to the next item
No API for pollable overlapped IO streams or IOCP streams on Windows
On UNIX we have the GUnix*Stream
s, which can operate non-blocking. On Windows we only have the blocking GWin32*Stream
s. For not having Windows stay a complete second-class citizen in GLib, it would probably make sense to add a bit more in this regard.
The wing
project has the WingInputStream
(overlapped IO) and the WingIOCPInputStream
(IOCP), which probably both would make sense to have directly in GIO instead. The other parts of wing
also seem potentially useful as they complement parts that we already have in GIO for UNIX (e.g. the named pipe connection is approximately GUnixConnection
).
Adding more API to GLib/GIO of course means more maintenance burden so that's maybe not desirable, but OTOH the current situation leaves Windows as a second class citizen and makes writing cross-platform applications harder than necessary. wing
seems reasonably well maintained, so moving API from there into GIO (which I assume the wing
maintainers would support) shouldn't make a big difference to the already existing maintenance burden of the GLib maintainers.
Any thoughts or opinions here?