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
|
//#define QPROCESS_DEBUG
|
||||||
|
|
||||||
#include <qdebug.h>
|
#include <qdebug.h>
|
||||||
#include <private/qdebug_p.h>
|
|
||||||
#include <qdir.h>
|
#include <qdir.h>
|
||||||
#include <qscopedvaluerollback.h>
|
#include <qscopedvaluerollback.h>
|
||||||
#if defined(Q_OS_WIN)
|
|
||||||
#include <qtimer.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "qprocess.h"
|
#include "qprocess.h"
|
||||||
#include "qprocess_p.h"
|
#include "qprocess_p.h"
|
||||||
@ -54,15 +50,8 @@
|
|||||||
#include <qbytearray.h>
|
#include <qbytearray.h>
|
||||||
#include <qdeadlinetimer.h>
|
#include <qdeadlinetimer.h>
|
||||||
#include <qcoreapplication.h>
|
#include <qcoreapplication.h>
|
||||||
#include <qsocketnotifier.h>
|
|
||||||
#include <qtimer.h>
|
#include <qtimer.h>
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
#include <qwineventnotifier.h>
|
|
||||||
#else
|
|
||||||
#include <private/qcore_unix_p.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if __has_include(<paths.h>)
|
#if __has_include(<paths.h>)
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
#endif
|
#endif
|
||||||
@ -807,44 +796,6 @@ QProcessPrivate::~QProcessPrivate()
|
|||||||
stdoutChannel.process->stdinChannel.clear();
|
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
|
\internal
|
||||||
*/
|
*/
|
||||||
@ -1064,36 +1015,6 @@ bool QProcessPrivate::_q_canReadStandardError()
|
|||||||
return tryReadFromChannel(&stderrChannel);
|
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
|
\internal
|
||||||
*/
|
*/
|
||||||
@ -1905,44 +1826,6 @@ qint64 QProcess::readData(char *data, qint64 maxlen)
|
|||||||
return 0;
|
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
|
Regardless of the current read channel, this function returns all
|
||||||
data available from the standard output of the process as a
|
data available from the standard output of the process as a
|
||||||
|
@ -330,14 +330,11 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
QProcessEnvironment environment;
|
QProcessEnvironment environment;
|
||||||
|
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
Q_PIPE childStartedPipe[2] = {INVALID_Q_PIPE, INVALID_Q_PIPE};
|
Q_PIPE childStartedPipe[2] = {INVALID_Q_PIPE, INVALID_Q_PIPE};
|
||||||
void destroyPipe(Q_PIPE pipe[2]);
|
|
||||||
|
|
||||||
QSocketNotifier *stateNotifier = nullptr;
|
QSocketNotifier *stateNotifier = nullptr;
|
||||||
|
|
||||||
int forkfd = -1;
|
int forkfd = -1;
|
||||||
|
#else
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
QTimer *stdinWriteTrigger = nullptr;
|
QTimer *stdinWriteTrigger = nullptr;
|
||||||
QWinEventNotifier *processFinishedNotifier = nullptr;
|
QWinEventNotifier *processFinishedNotifier = nullptr;
|
||||||
#endif
|
#endif
|
||||||
@ -378,6 +375,7 @@ public:
|
|||||||
qint64 readFromChannel(const Channel *channel, char *data, qint64 maxlen);
|
qint64 readFromChannel(const Channel *channel, char *data, qint64 maxlen);
|
||||||
bool writeToStdin();
|
bool writeToStdin();
|
||||||
|
|
||||||
|
void destroyPipe(Q_PIPE pipe[2]);
|
||||||
void cleanup();
|
void cleanup();
|
||||||
void setError(QProcess::ProcessError error, const QString &description = QString());
|
void setError(QProcess::ProcessError error, const QString &description = QString());
|
||||||
void setErrorAndEmit(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);
|
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.
|
Create the pipes to a QProcessPrivate::Channel.
|
||||||
*/
|
*/
|
||||||
@ -642,6 +657,52 @@ qint64 QProcessPrivate::readFromChannel(const Channel *channel, char *data, qint
|
|||||||
return bytesRead;
|
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()
|
bool QProcessPrivate::writeToStdin()
|
||||||
{
|
{
|
||||||
const char *data = writeBuffer.readPointer();
|
const char *data = writeBuffer.readPointer();
|
||||||
|
@ -39,6 +39,9 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
//#define QPROCESS_DEBUG
|
//#define QPROCESS_DEBUG
|
||||||
|
#include <qdebug.h>
|
||||||
|
#include <private/qdebug_p.h>
|
||||||
|
|
||||||
#include "qprocess.h"
|
#include "qprocess.h"
|
||||||
#include "qprocess_p.h"
|
#include "qprocess_p.h"
|
||||||
#include "qwindowspipereader_p.h"
|
#include "qwindowspipereader_p.h"
|
||||||
@ -50,9 +53,9 @@
|
|||||||
#include <qrandom.h>
|
#include <qrandom.h>
|
||||||
#include <qwineventnotifier.h>
|
#include <qwineventnotifier.h>
|
||||||
#include <qscopedvaluerollback.h>
|
#include <qscopedvaluerollback.h>
|
||||||
|
#include <qtimer.h>
|
||||||
#include <private/qsystemlibrary_p.h>
|
#include <private/qsystemlibrary_p.h>
|
||||||
#include <private/qthread_p.h>
|
#include <private/qthread_p.h>
|
||||||
#include <qdebug.h>
|
|
||||||
|
|
||||||
#include "private/qfsfileengine_p.h" // for longFileName
|
#include "private/qfsfileengine_p.h" // for longFileName
|
||||||
|
|
||||||
@ -375,6 +378,23 @@ void QProcessPrivate::closeChannel(Channel *channel)
|
|||||||
destroyPipe(channel->pipe);
|
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,
|
static QString qt_create_commandline(const QString &program, const QStringList &arguments,
|
||||||
const QString &nativeArguments)
|
const QString &nativeArguments)
|
||||||
{
|
{
|
||||||
@ -816,7 +836,6 @@ bool QProcessPrivate::waitForFinished(const QDeadlineTimer &deadline)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void QProcessPrivate::findExitCode()
|
void QProcessPrivate::findExitCode()
|
||||||
{
|
{
|
||||||
DWORD theExitCode;
|
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
|
qint64 QProcessPrivate::pipeWriterBytesToWrite() const
|
||||||
{
|
{
|
||||||
return stdinChannel.writer ? stdinChannel.writer->bytesToWrite() : qint64(0);
|
return stdinChannel.writer ? stdinChannel.writer->bytesToWrite() : qint64(0);
|
||||||
@ -844,6 +895,20 @@ void QProcessPrivate::_q_bytesWritten(qint64 bytes)
|
|||||||
_q_canWrite();
|
_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()
|
bool QProcessPrivate::writeToStdin()
|
||||||
{
|
{
|
||||||
Q_Q(QProcess);
|
Q_Q(QProcess);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user