Unverified Commit 93746a06 authored by Andre Heinecke's avatar Andre Heinecke
Browse files

Reduce inherited handles for Windows child proc

When starting the WindowsProcessDevice we would inherit
all handles marked as inhertiable to the child process.
This somehow leads to a problem on Network drives where
an open File handle to \device\afd is inherited. This
open File handle appears to cause Windows to keep the
stdout Handle of the child process open as it does not
fully terminate the child. This then causes a hang
in the ReadFile call.

This way we only inherit the three handles we want to
inherit. Which is much cleaner as it filters out a lot
of other handles to threads etc. which we do not want
to inherit.

GnuPG-Bug-Id: T6139
parent 6a55c1a2
Pipeline #220165 passed with stage
in 3 minutes and 7 seconds
......@@ -366,18 +366,68 @@ bool WindowsProcessDevice::Private::start(QIODevice::OpenMode mode)
const QString nativeWorkingDirectory = QDir::toNativeSeparators(mWorkingDirectory);
const wchar_t *wd = reinterpret_cast<const wchar_t *>(nativeWorkingDirectory.utf16());
qCDebug(KLEOPATRA_LOG) << "Spawning:" << args;
/* Filter out the handles to inherit only the three handles which we want to
* inherit. As a Qt Application we have a multitude of open handles which
* may or may not be inheritable. Testing has shown that this reduced about
* thirty handles. Open File handles in our child application can also cause the
* read pipe not to be closed correcly on exit. */
SIZE_T size;
bool suc = InitializeProcThreadAttributeList(NULL, 1, 0, &size) ||
GetLastError() == ERROR_INSUFFICIENT_BUFFER;
if (!suc) {
qCDebug(KLEOPATRA_LOG) << "Failed to get Attribute List size";
mError = getLastErrorString();
return false;
}
LPPROC_THREAD_ATTRIBUTE_LIST attributeList = reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST> (HeapAlloc(GetProcessHeap(), 0, size));
if (!attributeList) {
qCDebug(KLEOPATRA_LOG) << "Failed to Allocate Attribute List";
return false;
}
suc = InitializeProcThreadAttributeList(attributeList, 1, 0, &size);
if (!suc) {
qCDebug(KLEOPATRA_LOG) << "Failed to Initalize Attribute List";
mError = getLastErrorString();
return false;
}
HANDLE handles[3];
handles[0] = mStdOutWr;
handles[1] = mStdErrWr;
handles[2] = mStdInRd;
suc = UpdateProcThreadAttribute(attributeList,
0,
PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
handles,
3 * sizeof(HANDLE),
NULL,
NULL);
if (!suc) {
qCDebug(KLEOPATRA_LOG) << "Failed to Update Attribute List";
mError = getLastErrorString();
return false;
}
STARTUPINFOEX info;
ZeroMemory(&info, sizeof(info));
info.StartupInfo = siStartInfo;
info.StartupInfo.cb = sizeof(info); // You have to know this,..
info.lpAttributeList = attributeList;
// Now lets start
bool suc = CreateProcessW(proc,
cmdLine, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
CREATE_NO_WINDOW,// creation flags
NULL, // use parent's environment
wd, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
qCDebug(KLEOPATRA_LOG) << "Spawning:" << args;
suc = CreateProcessW(proc,
cmdLine, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT,// creation flags
NULL, // use parent's environment
wd, // use parent's current directory
&info.StartupInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
DeleteProcThreadAttributeList(attributeList);
HeapFree(GetProcessHeap(), 0, attributeList);
free(cmdLine);
if (!suc) {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment