[Interest] QProcess unbuffered
qt-maillist at hazardy.de
Tue Mar 7 23:23:00 CET 2023
That's right. It depends on the runtime, but I have not seen a process which
uses not a Microsoft provided runtime (of course I didn't check all the programs
And that's all I've found. It serves my purposes to the fullest.
From the code I reviewed back then (and remember it now) it unpacks the handles
directly to a HANDLE, which is pointer size (although it only uses the lower 32
bit). But Scott will tell us what the field width has to be for a 64 bit process.
Am 07.03.2023 um 23:06 schrieb Thiago Macieira:
> [quoting out of order]
> On Tuesday, 7 March 2023 12:57:59 PST Björn Schäpers wrote:
>> startInf.cbReserved2 = sizeof(HackedHandlePasser);
>> startInf.lpReserved2 = reinterpret_cast<LPBYTE>(&handles);
> These reserved fields are how the runtimes "pass file descriptors" to child
> processes. This mimics the Unix fork() behaviour that the parent's open file
> descriptors are available in the child, without implementing the full fork()
> behaviour. The fields are undocumented (AFAIK) but since both msvcrt and ucrt
> depend on the specific behaviours, they can't change.
> That includes these bit fields for flags:
>> #ifndef FOPEN
>> #define FOPEN 0x01
>> #ifndef FDEV
>> #define FDEV 0x40
>> handles.FlagsPerHandle = 0;
>> std::memset(&handles.FlagsPerHandle, FOPEN | FDEV, 2);
> According to the UCRT source code, the FDEV flag controls whether the standard
> streams will be buffered or not. The UCRT implementation of isatty() is a check
> to see if this flag is set.
> The UCRT source code isn't complete (ucrtbase isn't included AFAICS), so I
> couldn't find all details when trying to give you a more specific answer.
>> * I have the HANDLE32 because I start a 32 bit application from within a 64
>> bit, as far as I understood the structure needs the right HANDLE size, thus
>> for a 64 bit application it should be std:int64_t, but since I don't need
>> that I never tested it.
> The parent process wouldn't know whether the child is 32-bit or not, so I
> imagine the size must be fixed at 32 bits in order to be inheritable. If you
> have MSVC, you have access to the UCRT source code too and you can search for
> those two reserved fields to see if they hardcode to 32-bit or pointer sizes.
>> So when using it with QProcess I think one should copy the handles from the
>> STARTUPINFOW structure into this struct, then I think the normal QIODevice
>> interface should keep working. If one should clear the STARTF_USESTDHANDLES
>> flag I also don't know. I stopped my experiments when I achieved success
>> for my "simple" use case.
> QProcess uses CreateProcessW directly, not the _spawnv* CRT family of
> functions, which is why file descriptors aren't usually inherited via QProcess.
> I don't know either whether the STARTF_USESTDHANDLES flag must be cleared
> because they're handled at separate times.
> If this flag is passed, then the three handles in STARTUPINFO are passed to
> the child as its default handles, by the Win32 call itself. That means those
> handles are installed in the child before the runtime gets a chance to
> initialise and read the file descriptor table passed in those reserved fields.
> Whether the runtime overwrites the standard file descriptors or not, I couldn't
> find in the UCRT sources.
> And for the same reason, I can't tell either how the FDEV flag is set for the
> standard file descriptors from outside the file descriptor table.
> Moreover, please note that this is *runtime* -driven behaviour, not OS-
> mandated. So it's entirely possible that this executable that Scott wants to
> run operates differently because it uses a weird runtime. (Strictly speaking,
> it's the same on Unix systems, but all libcs have the same behaviour)
>  https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa
> Interest mailing list
> Interest at qt-project.org
More information about the Interest