[Interest] Enforce only stdin/out/err inherited with QProcess

christoph at cullmann.io christoph at cullmann.io
Tue Oct 1 09:34:55 CEST 2024


On 2024-09-25 20:15, christoph at cullmann.io wrote:
> On 2024-09-25 19:48, Thiago Macieira wrote:
>> On Wednesday 25 September 2024 08:36:47 GMT-7 christoph at cullmann.io 
>> wrote:
>>> > Since you want no handles but the standard three, would setting
>>> >
>>> >   args->inheritHandles = false
>>> >
>>> > suffice?
>>> 
>>> I tried that but for me that fails, I have no handles and unlike on
>>> Linux
>>> or Mac with the other code path I can no longer read any output from 
>>> the
>>> QProcess.
>>> 
>>> I did read a bit the Windows docs and the Qt code and its seems
>>> inheritHandles = TRUE
>>> is required if you use the STARTF_USESTDHANDLES flag in the startup 
>>> info
>>> like Qt does.
>> 
>> Ah, ok.
>> 
>> So it looks like doing what you tried to do by understanding Raymond 
>> Chen's
>> blog is the way to go... except it didn't work. Aside from the fact 
>> that you
>> didn't clean the thread's handle state or at least didn't include it 
>> in the
>> code you pasted, I see no reason it shouldn't work.
> 
> Yeah, that cleanup code would be after the start().
> 
>> 
>> Maybe there's some non-obvious mistake. Implementing it directly in
>> qprocess_win.cpp may make it work.
> 
> Ok, thanks for taking a look, I will see if I find the error or perhaps 
> somebody
> else has input, too.
> 
> At the moment I am just a bit confused what it might be, I did some 
> errors
> before I arrived with that, but then at least I got some API errors 
> back,
> now just the output from my called process won't arrive.

Just for future references, the issue was a duplicated file descriptor
passed to the function if channels are merged.

This works:

     // ensure the child process doesn't inherit our file handles
#ifdef Q_OS_WIN
     STARTUPINFOEX info;
     ZeroMemory(&info, sizeof(info));
     
m_process.setCreateProcessArgumentsModifier([&info](QProcess::CreateProcessArguments 
*args) {
         // only keep the handles that we have in args->startupInfo
         SIZE_T size = 0;
         LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList = NULL;
         UR_ENSURE(InitializeProcThreadAttributeList(NULL, 1, 0, &size) 
|| (GetLastError() == ERROR_INSUFFICIENT_BUFFER));
         UR_ENSURE((lpAttributeList = 
reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(HeapAlloc(GetProcessHeap(), 
0, size))));
         UR_ENSURE(InitializeProcThreadAttributeList(lpAttributeList, 1, 
0, &size));

         // ensure all handles are inheritable
         for (auto handle : {args->startupInfo->hStdInput, 
args->startupInfo->hStdOutput, args->startupInfo->hStdError}) {
             UR_ENSURE(SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 
HANDLE_FLAG_INHERIT));
         }

         const auto numberOfUniqueHandles = 
(args->startupInfo->hStdOutput == args->startupInfo->hStdError) ? 2 : 3;
         UR_ENSURE(UpdateProcThreadAttribute(
             lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, 
&args->startupInfo->hStdInput, numberOfUniqueHandles * sizeof(HANDLE), 
NULL, NULL));

         info.StartupInfo = *(args->startupInfo);
         info.StartupInfo.cb = sizeof(info);
         info.lpAttributeList = lpAttributeList;
         args->flags |= EXTENDED_STARTUPINFO_PRESENT;
         args->startupInfo = &info.StartupInfo;
     });
#else
     QProcess::UnixProcessParameters params;
     params.flags = QProcess::UnixProcessFlag::CloseFileDescriptors;
     params.lowestFileDescriptorToClose = 0;
     m_process.setUnixProcessParameters(params);
#endif

     // dispatch to internal process
     m_process.start(program, arguments, mode);

#ifdef Q_OS_WIN
     // cleanup only if the setCreateProcessArgumentsModifier functor was 
executed
     if (info.lpAttributeList) {
         DeleteProcThreadAttributeList(info.lpAttributeList);
         HeapFree(GetProcessHeap(), 0, info.lpAttributeList);
     }
#endif

Greetings
Christoph

> 
> Greetings
> Christoph
> _______________________________________________
> Interest mailing list
> Interest at qt-project.org
> https://lists.qt-project.org/listinfo/interest


More information about the Interest mailing list