diff options
Diffstat (limited to 'src/corelib/io/qprocess_win.cpp')
-rw-r--r-- | src/corelib/io/qprocess_win.cpp | 123 |
1 files changed, 71 insertions, 52 deletions
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index 8c4e5b41b4..cb4b2f9f91 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -149,7 +149,26 @@ static void qt_create_pipe(Q_PIPE *pipe, bool isInputPipe) } // Wait until connection is in place. - ConnectNamedPipe(hServer, NULL); + OVERLAPPED overlapped; + ZeroMemory(&overlapped, sizeof(overlapped)); + overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (ConnectNamedPipe(hServer, &overlapped) == 0) { + DWORD dwError = GetLastError(); + switch (dwError) { + case ERROR_PIPE_CONNECTED: + break; + case ERROR_IO_PENDING: + WaitForSingleObject(overlapped.hEvent, INFINITE); + break; + default: + qErrnoWarning(dwError, "QProcess: ConnectNamedPipe failed."); + CloseHandle(overlapped.hEvent); + CloseHandle(hClient); + CloseHandle(hServer); + return; + } + } + CloseHandle(overlapped.hEvent); if (isInputPipe) { pipe[0] = hClient; @@ -183,7 +202,8 @@ bool QProcessPrivate::openChannel(Channel &channel) &stderrChannel.pipe[1], 0, TRUE, DUPLICATE_SAME_ACCESS); } - if (channel.type == Channel::Normal) { + switch (channel.type) { + case Channel::Normal: // we're piping this channel to our own process if (&channel == &stdinChannel) { if (inputChannelMode != QProcess::ForwardedInputChannel) { @@ -223,9 +243,8 @@ bool QProcessPrivate::openChannel(Channel &channel) channel.reader->startAsyncRead(); } } - return true; - } else if (channel.type == Channel::Redirect) { + case Channel::Redirect: { // we're redirecting the channel to/from a file SECURITY_ATTRIBUTES secAtt = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; @@ -270,65 +289,65 @@ bool QProcessPrivate::openChannel(Channel &channel) } cleanup(); return false; - } else { + } + case Channel::PipeSource: { Q_ASSERT_X(channel.process, "QProcess::start", "Internal error"); + // we are the source + Channel *source = &channel; + Channel *sink = &channel.process->stdinChannel; + + if (source->pipe[1] != INVALID_Q_PIPE) { + // already constructed by the sink + // make it inheritable + HANDLE tmpHandle = source->pipe[1]; + if (!DuplicateHandle(GetCurrentProcess(), tmpHandle, + GetCurrentProcess(), &source->pipe[1], + 0, TRUE, DUPLICATE_SAME_ACCESS)) { + return false; + } - Channel *source; - Channel *sink; + CloseHandle(tmpHandle); + return true; + } - if (channel.type == Channel::PipeSource) { - // we are the source - source = &channel; - sink = &channel.process->stdinChannel; + Q_ASSERT(source == &stdoutChannel); + Q_ASSERT(sink->process == this && sink->type == Channel::PipeSink); - if (source->pipe[1] != INVALID_Q_PIPE) { - // already constructed by the sink - // make it inheritable - HANDLE tmpHandle = source->pipe[1]; - if (!DuplicateHandle(GetCurrentProcess(), tmpHandle, - GetCurrentProcess(), &source->pipe[1], - 0, TRUE, DUPLICATE_SAME_ACCESS)) - return false; + qt_create_pipe(source->pipe, /* in = */ false); // source is stdout + sink->pipe[0] = source->pipe[0]; + source->pipe[0] = INVALID_Q_PIPE; - CloseHandle(tmpHandle); - return true; + return true; + } + case Channel::PipeSink: { // we are the sink; + Q_ASSERT_X(channel.process, "QProcess::start", "Internal error"); + Channel *source = &channel.process->stdoutChannel; + Channel *sink = &channel; + + if (sink->pipe[0] != INVALID_Q_PIPE) { + // already constructed by the source + // make it inheritable + HANDLE tmpHandle = sink->pipe[0]; + if (!DuplicateHandle(GetCurrentProcess(), tmpHandle, + GetCurrentProcess(), &sink->pipe[0], + 0, TRUE, DUPLICATE_SAME_ACCESS)) { + return false; } - Q_ASSERT(source == &stdoutChannel); - Q_ASSERT(sink->process == this && sink->type == Channel::PipeSink); - - qt_create_pipe(source->pipe, /* in = */ false); // source is stdout - sink->pipe[0] = source->pipe[0]; - source->pipe[0] = INVALID_Q_PIPE; - + CloseHandle(tmpHandle); return true; - } else { - // we are the sink; - source = &channel.process->stdoutChannel; - sink = &channel; - - if (sink->pipe[0] != INVALID_Q_PIPE) { - // already constructed by the source - // make it inheritable - HANDLE tmpHandle = sink->pipe[0]; - if (!DuplicateHandle(GetCurrentProcess(), tmpHandle, - GetCurrentProcess(), &sink->pipe[0], - 0, TRUE, DUPLICATE_SAME_ACCESS)) - return false; - - CloseHandle(tmpHandle); - return true; - } - Q_ASSERT(sink == &stdinChannel); - Q_ASSERT(source->process == this && source->type == Channel::PipeSource); + } + Q_ASSERT(sink == &stdinChannel); + Q_ASSERT(source->process == this && source->type == Channel::PipeSource); - qt_create_pipe(sink->pipe, /* in = */ true); // sink is stdin - source->pipe[1] = sink->pipe[1]; - sink->pipe[1] = INVALID_Q_PIPE; + qt_create_pipe(sink->pipe, /* in = */ true); // sink is stdin + source->pipe[1] = sink->pipe[1]; + sink->pipe[1] = INVALID_Q_PIPE; - return true; - } + return true; } + } // switch (channel.type) + return false; } void QProcessPrivate::destroyPipe(Q_PIPE pipe[2]) |