bool QProcessPrivate::waitForFinished(int msecs) { Q_Q(QProcess); #if defined QPROCESS_DEBUG qDebug("QProcessPrivate::waitForFinished(%d)", msecs); #endif QIncrementalSleepTimer timer(msecs); forever { if (!pid) return true; if (WaitForSingleObject(pid->hProcess, timer.nextSleepTime()) == WAIT_OBJECT_0) { _q_processDied(); return true; } if (timer.hasTimedOut()) break; } processError = QProcess::Timedout; q->setErrorString(QProcess::tr("Process operation timed out")); return false; }
bool QProcessPrivate::waitForReadyRead(int msecs) { Q_Q(QProcess); QIncrementalSleepTimer timer(msecs); forever { if (!writeBuffer.isEmpty() && !_q_canWrite()) return false; if (pipeWriter && pipeWriter->waitForWrite(0)) timer.resetIncrements(); if (processChannelMode != QProcess::ForwardedChannels && ((stdoutReader && stdoutReader->waitForReadyRead(0)) || (stderrReader && stderrReader->waitForReadyRead(0)))) return true; if (!pid) return false; if (WaitForSingleObject(pid->hProcess, 0) == WAIT_OBJECT_0) { bool readyReadEmitted = drainOutputPipes(this); _q_processDied(); return readyReadEmitted; } Sleep(timer.nextSleepTime()); if (timer.hasTimedOut()) break; } processError = QProcess::Timedout; q->setErrorString(QProcess::tr("Process operation timed out")); return false; }
bool QProcessPrivate::waitForReadyRead(int msecs) { Q_Q(QProcess); #if defined(Q_OS_WINCE) processError = QProcess::ReadError; q->setErrorString(QProcess::tr("Error reading from process")); emit q->error(processError); return false; #endif QIncrementalSleepTimer timer(msecs); forever { if (!writeBuffer.isEmpty() && !_q_canWrite()) return false; if (pipeWriter && pipeWriter->waitForWrite(0)) timer.resetIncrements(); bool readyReadEmitted = false; if (bytesAvailableFromStdout() != 0) { readyReadEmitted = _q_canReadStandardOutput() ? true : readyReadEmitted; timer.resetIncrements(); } if (bytesAvailableFromStderr() != 0) { readyReadEmitted = _q_canReadStandardError() ? true : readyReadEmitted; timer.resetIncrements(); } if (readyReadEmitted) return true; if (!pid) return false; if (WaitForSingleObject(pid->hProcess, 0) == WAIT_OBJECT_0) { // find the return value if there is noew data to read _q_processDied(); return false; } Sleep(timer.nextSleepTime()); if (timer.hasTimedOut()) break; } processError = QProcess::Timedout; q->setErrorString(QProcess::tr("Process operation timed out")); return false; }
bool QProcessPrivate::waitForFinished(int msecs) { Q_Q(QProcess); #if defined QPROCESS_DEBUG qDebug("QProcessPrivate::waitForFinished(%d)", msecs); #endif if (!pid) return true; if (WaitForSingleObject(pid->hProcess, msecs == -1 ? INFINITE : msecs) == WAIT_OBJECT_0) { _q_processDied(); return true; } setError(QProcess::Timedout); return false; }
bool QProcessPrivate::waitForFinished(int msecs) { Q_Q(QProcess); #if defined QPROCESS_DEBUG qDebug("QProcessPrivate::waitForFinished(%d)", msecs); #endif QIncrementalSleepTimer timer(msecs); forever { if (!writeBuffer.isEmpty() && !_q_canWrite()) return false; if (pipeWriter && pipeWriter->waitForWrite(0)) timer.resetIncrements(); if (bytesAvailableFromStdout() != 0) { _q_canReadStandardOutput(); timer.resetIncrements(); } if (bytesAvailableFromStderr() != 0) { _q_canReadStandardError(); timer.resetIncrements(); } if (!pid) return true; if (WaitForSingleObject(pid->hProcess, timer.nextSleepTime()) == WAIT_OBJECT_0) { _q_processDied(); return true; } if (timer.hasTimedOut()) break; } processError = QProcess::Timedout; q->setErrorString(QProcess::tr("Process operation timed out")); return false; }
bool QProcessPrivate::waitForFinished(int msecs) { Q_Q(QProcess); #if defined QPROCESS_DEBUG qDebug("QProcessPrivate::waitForFinished(%d)", msecs); #endif QIncrementalSleepTimer timer(msecs); forever { if (!stdinChannel.buffer.isEmpty() && !_q_canWrite()) return false; if (stdinChannel.writer && stdinChannel.writer->waitForWrite(0)) timer.resetIncrements(); if (stdoutChannel.reader && stdoutChannel.reader->waitForReadyRead(0)) timer.resetIncrements(); if (stderrChannel.reader && stderrChannel.reader->waitForReadyRead(0)) timer.resetIncrements(); if (!pid) { drainOutputPipes(); return true; } if (WaitForSingleObject(pid->hProcess, timer.nextSleepTime()) == WAIT_OBJECT_0) { drainOutputPipes(); _q_processDied(); return true; } if (timer.hasTimedOut()) break; } processError = QProcess::Timedout; q->setErrorString(QProcess::tr("Process operation timed out")); return false; }
void QProcessPrivate::startProcess() { Q_Q(QProcess); bool success = false; if (pid) { CloseHandle(pid->hThread); CloseHandle(pid->hProcess); delete pid; pid = 0; } pid = new PROCESS_INFORMATION; memset(pid, 0, sizeof(PROCESS_INFORMATION)); q->setProcessState(QProcess::Starting); QString args = qt_create_commandline(QString(), arguments); if (!nativeArguments.isEmpty()) { if (!args.isEmpty()) args += QLatin1Char(' '); args += nativeArguments; } #if defined QPROCESS_DEBUG qDebug("Creating process"); qDebug(" program : [%s]", program.toLatin1().constData()); qDebug(" args : %s", args.toLatin1().constData()); qDebug(" pass environment : %s", environment.isEmpty() ? "no" : "yes"); #endif QString fullPathProgram = program; if (!QDir::isAbsolutePath(fullPathProgram)) fullPathProgram = QFileInfo(fullPathProgram).absoluteFilePath(); fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\')); success = CreateProcess((wchar_t*)fullPathProgram.utf16(), (wchar_t*)args.utf16(), 0, 0, false, 0, 0, 0, 0, pid); if (!success) { cleanup(); processError = QProcess::FailedToStart; emit q->error(processError); q->setProcessState(QProcess::NotRunning); return; } q->setProcessState(QProcess::Running); // User can call kill()/terminate() from the stateChanged() slot // so check before proceeding if (!pid) return; if (threadData->hasEventDispatcher()) { processFinishedNotifier = new QWinEventNotifier(pid->hProcess, q); QObject::connect(processFinishedNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_processDied())); processFinishedNotifier->setEnabled(true); } // give the process a chance to start ... Sleep(SLEEPMIN * 2); _q_startupNotification(); }
bool QProcessPrivate::waitForBytesWritten(int msecs) { Q_Q(QProcess); QIncrementalSleepTimer timer(msecs); forever { // Check if we have any data pending: the pipe writer has // bytes waiting to written, or it has written data since the // last time we called pipeWriter->waitForWrite(). bool pendingDataInPipe = pipeWriter && (pipeWriter->bytesToWrite() || pipeWriter->hadWritten()); // If we don't have pending data, and our write buffer is // empty, we fail. if (!pendingDataInPipe && writeBuffer.isEmpty()) return false; // If we don't have pending data and we do have data in our // write buffer, try to flush that data over to the pipe // writer. Fail on error. if (!pendingDataInPipe) { if (!_q_canWrite()) return false; } // Wait for the pipe writer to acknowledge that it has // written. This will succeed if either the pipe writer has // already written the data, or if it manages to write data // within the given timeout. If the write buffer was non-empty // and the pipeWriter is now dead, that means _q_canWrite() // destroyed the writer after it successfully wrote the last // batch. if (!pipeWriter || pipeWriter->waitForWrite(0)) return true; // If we wouldn't write anything, check if we can read stdout. if (bytesAvailableFromStdout() != 0) { _q_canReadStandardOutput(); timer.resetIncrements(); } // Check if we can read stderr. if (bytesAvailableFromStderr() != 0) { _q_canReadStandardError(); timer.resetIncrements(); } // Check if the process died while reading. if (!pid) return false; // Wait for the process to signal any change in its state, // such as incoming data, or if the process died. if (WaitForSingleObject(pid->hProcess, 0) == WAIT_OBJECT_0) { _q_processDied(); return false; } // Only wait for as long as we've been asked. if (timer.hasTimedOut()) break; } processError = QProcess::Timedout; q->setErrorString(QProcess::tr("Process operation timed out")); return false; }
void QProcessPrivate::startProcess() { Q_Q(QProcess); bool success = false; if (pid) { CloseHandle(pid->hThread); CloseHandle(pid->hProcess); delete pid; pid = 0; } pid = new PROCESS_INFORMATION; memset(pid, 0, sizeof(PROCESS_INFORMATION)); q->setProcessState(QProcess::Starting); if (!createChannel(stdinChannel) || !createChannel(stdoutChannel) || !createChannel(stderrChannel)) return; QString args = qt_create_commandline(program, arguments); QByteArray envlist; if (environment.d.constData()) envlist = qt_create_environment(environment.d.constData()->hash); if (!nativeArguments.isEmpty()) { if (!args.isEmpty()) args += QLatin1Char(' '); args += nativeArguments; } #if defined QPROCESS_DEBUG qDebug("Creating process"); qDebug(" program : [%s]", program.toLatin1().constData()); qDebug(" args : %s", args.toLatin1().constData()); qDebug(" pass environment : %s", environment.isEmpty() ? "no" : "yes"); #endif // Forwarded channels must not set the CREATE_NO_WINDOW flag because this // will render the stdout/stderr handles we're passing useless. DWORD dwCreationFlags = (processChannelMode == QProcess::ForwardedChannels ? 0 : CREATE_NO_WINDOW); dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT; STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, 0, 0, 0, STARTF_USESTDHANDLES, 0, 0, 0, stdinChannel.pipe[0], stdoutChannel.pipe[1], stderrChannel.pipe[1] }; success = CreateProcess(0, (wchar_t*)args.utf16(), 0, 0, TRUE, dwCreationFlags, environment.isEmpty() ? 0 : envlist.data(), workingDirectory.isEmpty() ? 0 : (wchar_t*)QDir::toNativeSeparators(workingDirectory).utf16(), &startupInfo, pid); if (!success) { // Capture the error string before we do CloseHandle below q->setErrorString(QProcess::tr("Process failed to start: %1").arg(qt_error_string())); } if (stdinChannel.pipe[0] != INVALID_Q_PIPE) { CloseHandle(stdinChannel.pipe[0]); stdinChannel.pipe[0] = INVALID_Q_PIPE; } if (stdoutChannel.pipe[1] != INVALID_Q_PIPE) { CloseHandle(stdoutChannel.pipe[1]); stdoutChannel.pipe[1] = INVALID_Q_PIPE; } if (stderrChannel.pipe[1] != INVALID_Q_PIPE) { CloseHandle(stderrChannel.pipe[1]); stderrChannel.pipe[1] = INVALID_Q_PIPE; } if (!success) { cleanup(); processError = QProcess::FailedToStart; emit q->error(processError); q->setProcessState(QProcess::NotRunning); return; } q->setProcessState(QProcess::Running); // User can call kill()/terminate() from the stateChanged() slot // so check before proceeding if (!pid) return; if (threadData->eventDispatcher) { processFinishedNotifier = new QWinEventNotifier(pid->hProcess, q); QObject::connect(processFinishedNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_processDied())); processFinishedNotifier->setEnabled(true); notifier = new QTimer(q); QObject::connect(notifier, SIGNAL(timeout()), q, SLOT(_q_notified())); notifier->start(NOTIFYTIMEOUT); } _q_startupNotification(); }