QProcess: untangle platform-specific details
- add missing #ifdef in header file; - split some functions (writeData(), _q_canWrite(), cleanup()) into their platform-specific implementations. Change-Id: I4e7c1c377ec8468ed120d38acf2543eef9316c01 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
This commit is contained in:
parent
467b39d52c
commit
f03e9164c0
@ -41,12 +41,8 @@
|
||||
//#define QPROCESS_DEBUG
|
||||
|
||||
#include <qdebug.h>
|
||||
#include <private/qdebug_p.h>
|
||||
#include <qdir.h>
|
||||
#include <qscopedvaluerollback.h>
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <qtimer.h>
|
||||
#endif
|
||||
|
||||
#include "qprocess.h"
|
||||
#include "qprocess_p.h"
|
||||
@ -54,15 +50,8 @@
|
||||
#include <qbytearray.h>
|
||||
#include <qdeadlinetimer.h>
|
||||
#include <qcoreapplication.h>
|
||||
#include <qsocketnotifier.h>
|
||||
#include <qtimer.h>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <qwineventnotifier.h>
|
||||
#else
|
||||
#include <private/qcore_unix_p.h>
|
||||
#endif
|
||||
|
||||
#if __has_include(<paths.h>)
|
||||
#include <paths.h>
|
||||
#endif
|
||||
@ -807,44 +796,6 @@ QProcessPrivate::~QProcessPrivate()
|
||||
stdoutChannel.process->stdinChannel.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
void QProcessPrivate::cleanup()
|
||||
{
|
||||
q_func()->setProcessState(QProcess::NotRunning);
|
||||
#ifdef Q_OS_WIN
|
||||
if (stdinWriteTrigger) {
|
||||
delete stdinWriteTrigger;
|
||||
stdinWriteTrigger = 0;
|
||||
}
|
||||
if (processFinishedNotifier) {
|
||||
delete processFinishedNotifier;
|
||||
processFinishedNotifier = 0;
|
||||
}
|
||||
if (pid) {
|
||||
CloseHandle(pid->hThread);
|
||||
CloseHandle(pid->hProcess);
|
||||
delete pid;
|
||||
pid = nullptr;
|
||||
}
|
||||
#else
|
||||
pid = 0;
|
||||
#endif
|
||||
|
||||
if (stateNotifier) {
|
||||
delete stateNotifier;
|
||||
stateNotifier = nullptr;
|
||||
}
|
||||
closeChannels();
|
||||
destroyPipe(childStartedPipe);
|
||||
#ifdef Q_OS_UNIX
|
||||
if (forkfd != -1)
|
||||
qt_safe_close(forkfd);
|
||||
forkfd = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
@ -1064,36 +1015,6 @@ bool QProcessPrivate::_q_canReadStandardError()
|
||||
return tryReadFromChannel(&stderrChannel);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
bool QProcessPrivate::_q_canWrite()
|
||||
{
|
||||
if (writeBuffer.isEmpty()) {
|
||||
#ifdef Q_OS_WIN
|
||||
if (stdinChannel.closed && pipeWriterBytesToWrite() == 0)
|
||||
closeWriteChannel();
|
||||
#else
|
||||
if (stdinChannel.notifier)
|
||||
stdinChannel.notifier->setEnabled(false);
|
||||
#endif
|
||||
#if defined QPROCESS_DEBUG
|
||||
qDebug("QProcessPrivate::canWrite(), not writing anything (empty write buffer).");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool writeSucceeded = writeToStdin();
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
if (writeBuffer.isEmpty() && stdinChannel.closed)
|
||||
closeWriteChannel();
|
||||
else if (stdinChannel.notifier)
|
||||
stdinChannel.notifier->setEnabled(!writeBuffer.isEmpty());
|
||||
#endif
|
||||
return writeSucceeded;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
@ -1905,44 +1826,6 @@ qint64 QProcess::readData(char *data, qint64 maxlen)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \reimp
|
||||
*/
|
||||
qint64 QProcess::writeData(const char *data, qint64 len)
|
||||
{
|
||||
Q_D(QProcess);
|
||||
|
||||
if (d->stdinChannel.closed) {
|
||||
#if defined QPROCESS_DEBUG
|
||||
qDebug("QProcess::writeData(%p \"%s\", %lld) == 0 (write channel closing)",
|
||||
data, QtDebugUtils::toPrintable(data, len, 16).constData(), len);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
if (!d->stdinWriteTrigger) {
|
||||
d->stdinWriteTrigger = new QTimer;
|
||||
d->stdinWriteTrigger->setSingleShot(true);
|
||||
QObjectPrivate::connect(d->stdinWriteTrigger, &QTimer::timeout,
|
||||
d, &QProcessPrivate::_q_canWrite);
|
||||
}
|
||||
#endif
|
||||
|
||||
d->write(data, len);
|
||||
#ifdef Q_OS_WIN
|
||||
if (!d->stdinWriteTrigger->isActive())
|
||||
d->stdinWriteTrigger->start();
|
||||
#else
|
||||
if (d->stdinChannel.notifier)
|
||||
d->stdinChannel.notifier->setEnabled(true);
|
||||
#endif
|
||||
#if defined QPROCESS_DEBUG
|
||||
qDebug("QProcess::writeData(%p \"%s\", %lld) == %lld (written to buffer)",
|
||||
data, QtDebugUtils::toPrintable(data, len, 16).constData(), len, len);
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
|
||||
/*!
|
||||
Regardless of the current read channel, this function returns all
|
||||
data available from the standard output of the process as a
|
||||
|
@ -330,14 +330,11 @@ public:
|
||||
#endif
|
||||
QProcessEnvironment environment;
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
Q_PIPE childStartedPipe[2] = {INVALID_Q_PIPE, INVALID_Q_PIPE};
|
||||
void destroyPipe(Q_PIPE pipe[2]);
|
||||
|
||||
QSocketNotifier *stateNotifier = nullptr;
|
||||
|
||||
int forkfd = -1;
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#else
|
||||
QTimer *stdinWriteTrigger = nullptr;
|
||||
QWinEventNotifier *processFinishedNotifier = nullptr;
|
||||
#endif
|
||||
@ -378,6 +375,7 @@ public:
|
||||
qint64 readFromChannel(const Channel *channel, char *data, qint64 maxlen);
|
||||
bool writeToStdin();
|
||||
|
||||
void destroyPipe(Q_PIPE pipe[2]);
|
||||
void cleanup();
|
||||
void setError(QProcess::ProcessError error, const QString &description = QString());
|
||||
void setErrorAndEmit(QProcess::ProcessError error, const QString &description = QString());
|
||||
|
@ -276,6 +276,21 @@ void QProcessPrivate::closeChannel(Channel *channel)
|
||||
destroyPipe(channel->pipe);
|
||||
}
|
||||
|
||||
void QProcessPrivate::cleanup()
|
||||
{
|
||||
q_func()->setProcessState(QProcess::NotRunning);
|
||||
|
||||
closeChannels();
|
||||
delete stateNotifier;
|
||||
stateNotifier = nullptr;
|
||||
destroyPipe(childStartedPipe);
|
||||
pid = 0;
|
||||
if (forkfd != -1) {
|
||||
qt_safe_close(forkfd);
|
||||
forkfd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Create the pipes to a QProcessPrivate::Channel.
|
||||
*/
|
||||
@ -642,6 +657,52 @@ qint64 QProcessPrivate::readFromChannel(const Channel *channel, char *data, qint
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
/*! \reimp
|
||||
*/
|
||||
qint64 QProcess::writeData(const char *data, qint64 len)
|
||||
{
|
||||
Q_D(QProcess);
|
||||
|
||||
if (d->stdinChannel.closed) {
|
||||
#if defined QPROCESS_DEBUG
|
||||
qDebug("QProcess::writeData(%p \"%s\", %lld) == 0 (write channel closing)",
|
||||
data, QtDebugUtils::toPrintable(data, len, 16).constData(), len);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
d->write(data, len);
|
||||
if (d->stdinChannel.notifier)
|
||||
d->stdinChannel.notifier->setEnabled(true);
|
||||
|
||||
#if defined QPROCESS_DEBUG
|
||||
qDebug("QProcess::writeData(%p \"%s\", %lld) == %lld (written to buffer)",
|
||||
data, QtDebugUtils::toPrintable(data, len, 16).constData(), len, len);
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
|
||||
bool QProcessPrivate::_q_canWrite()
|
||||
{
|
||||
if (writeBuffer.isEmpty()) {
|
||||
if (stdinChannel.notifier)
|
||||
stdinChannel.notifier->setEnabled(false);
|
||||
#if defined QPROCESS_DEBUG
|
||||
qDebug("QProcessPrivate::canWrite(), not writing anything (empty write buffer).");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool writeSucceeded = writeToStdin();
|
||||
|
||||
if (writeBuffer.isEmpty() && stdinChannel.closed)
|
||||
closeWriteChannel();
|
||||
else if (stdinChannel.notifier)
|
||||
stdinChannel.notifier->setEnabled(!writeBuffer.isEmpty());
|
||||
|
||||
return writeSucceeded;
|
||||
}
|
||||
|
||||
bool QProcessPrivate::writeToStdin()
|
||||
{
|
||||
const char *data = writeBuffer.readPointer();
|
||||
|
@ -39,6 +39,9 @@
|
||||
****************************************************************************/
|
||||
|
||||
//#define QPROCESS_DEBUG
|
||||
#include <qdebug.h>
|
||||
#include <private/qdebug_p.h>
|
||||
|
||||
#include "qprocess.h"
|
||||
#include "qprocess_p.h"
|
||||
#include "qwindowspipereader_p.h"
|
||||
@ -50,9 +53,9 @@
|
||||
#include <qrandom.h>
|
||||
#include <qwineventnotifier.h>
|
||||
#include <qscopedvaluerollback.h>
|
||||
#include <qtimer.h>
|
||||
#include <private/qsystemlibrary_p.h>
|
||||
#include <private/qthread_p.h>
|
||||
#include <qdebug.h>
|
||||
|
||||
#include "private/qfsfileengine_p.h" // for longFileName
|
||||
|
||||
@ -375,6 +378,23 @@ void QProcessPrivate::closeChannel(Channel *channel)
|
||||
destroyPipe(channel->pipe);
|
||||
}
|
||||
|
||||
void QProcessPrivate::cleanup()
|
||||
{
|
||||
q_func()->setProcessState(QProcess::NotRunning);
|
||||
|
||||
closeChannels();
|
||||
delete stdinWriteTrigger;
|
||||
stdinWriteTrigger = nullptr;
|
||||
delete processFinishedNotifier;
|
||||
processFinishedNotifier = nullptr;
|
||||
if (pid) {
|
||||
CloseHandle(pid->hThread);
|
||||
CloseHandle(pid->hProcess);
|
||||
delete pid;
|
||||
pid = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static QString qt_create_commandline(const QString &program, const QStringList &arguments,
|
||||
const QString &nativeArguments)
|
||||
{
|
||||
@ -816,7 +836,6 @@ bool QProcessPrivate::waitForFinished(const QDeadlineTimer &deadline)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void QProcessPrivate::findExitCode()
|
||||
{
|
||||
DWORD theExitCode;
|
||||
@ -828,6 +847,38 @@ void QProcessPrivate::findExitCode()
|
||||
}
|
||||
}
|
||||
|
||||
/*! \reimp
|
||||
*/
|
||||
qint64 QProcess::writeData(const char *data, qint64 len)
|
||||
{
|
||||
Q_D(QProcess);
|
||||
|
||||
if (d->stdinChannel.closed) {
|
||||
#if defined QPROCESS_DEBUG
|
||||
qDebug("QProcess::writeData(%p \"%s\", %lld) == 0 (write channel closing)",
|
||||
data, QtDebugUtils::toPrintable(data, len, 16).constData(), len);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!d->stdinWriteTrigger) {
|
||||
d->stdinWriteTrigger = new QTimer;
|
||||
d->stdinWriteTrigger->setSingleShot(true);
|
||||
QObjectPrivate::connect(d->stdinWriteTrigger, &QTimer::timeout,
|
||||
d, &QProcessPrivate::_q_canWrite);
|
||||
}
|
||||
|
||||
d->write(data, len);
|
||||
if (!d->stdinWriteTrigger->isActive())
|
||||
d->stdinWriteTrigger->start();
|
||||
|
||||
#if defined QPROCESS_DEBUG
|
||||
qDebug("QProcess::writeData(%p \"%s\", %lld) == %lld (written to buffer)",
|
||||
data, QtDebugUtils::toPrintable(data, len, 16).constData(), len, len);
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
|
||||
qint64 QProcessPrivate::pipeWriterBytesToWrite() const
|
||||
{
|
||||
return stdinChannel.writer ? stdinChannel.writer->bytesToWrite() : qint64(0);
|
||||
@ -844,6 +895,20 @@ void QProcessPrivate::_q_bytesWritten(qint64 bytes)
|
||||
_q_canWrite();
|
||||
}
|
||||
|
||||
bool QProcessPrivate::_q_canWrite()
|
||||
{
|
||||
if (writeBuffer.isEmpty()) {
|
||||
if (stdinChannel.closed && pipeWriterBytesToWrite() == 0)
|
||||
closeWriteChannel();
|
||||
#if defined QPROCESS_DEBUG
|
||||
qDebug("QProcessPrivate::canWrite(), not writing anything (empty write buffer).");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
return writeToStdin();
|
||||
}
|
||||
|
||||
bool QProcessPrivate::writeToStdin()
|
||||
{
|
||||
Q_Q(QProcess);
|
||||
|
Loading…
x
Reference in New Issue
Block a user