Integrate QProcess into QIODevice's multistreaming infrastructure
As a result, this patch eliminates double-buffering in QProcess. Change-Id: I436faa4a5ffc28ce77f959dd6089bef400ac39f6 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
This commit is contained in:
parent
8f92baf5c9
commit
7ff655360f
@ -866,7 +866,8 @@ void QProcessPrivate::Channel::clear()
|
|||||||
*/
|
*/
|
||||||
QProcessPrivate::QProcessPrivate()
|
QProcessPrivate::QProcessPrivate()
|
||||||
{
|
{
|
||||||
processChannel = QProcess::StandardOutput;
|
readBufferChunkSize = QRINGBUFFER_CHUNKSIZE;
|
||||||
|
writeBufferChunkSize = QRINGBUFFER_CHUNKSIZE;
|
||||||
processChannelMode = QProcess::SeparateChannels;
|
processChannelMode = QProcess::SeparateChannels;
|
||||||
inputChannelMode = QProcess::ManagedInputChannel;
|
inputChannelMode = QProcess::ManagedInputChannel;
|
||||||
processError = QProcess::UnknownError;
|
processError = QProcess::UnknownError;
|
||||||
@ -1017,10 +1018,15 @@ bool QProcessPrivate::tryReadFromChannel(Channel *channel)
|
|||||||
if (available == 0)
|
if (available == 0)
|
||||||
available = 1; // always try to read at least one byte
|
available = 1; // always try to read at least one byte
|
||||||
|
|
||||||
char *ptr = channel->buffer.reserve(available);
|
QProcess::ProcessChannel channelIdx = (channel == &stdoutChannel
|
||||||
|
? QProcess::StandardOutput
|
||||||
|
: QProcess::StandardError);
|
||||||
|
Q_ASSERT(readBuffers.size() > int(channelIdx));
|
||||||
|
QRingBuffer &readBuffer = readBuffers[int(channelIdx)];
|
||||||
|
char *ptr = readBuffer.reserve(available);
|
||||||
qint64 readBytes = readFromChannel(channel, ptr, available);
|
qint64 readBytes = readFromChannel(channel, ptr, available);
|
||||||
if (readBytes <= 0)
|
if (readBytes <= 0)
|
||||||
channel->buffer.chop(available);
|
readBuffer.chop(available);
|
||||||
if (readBytes == -2) {
|
if (readBytes == -2) {
|
||||||
// EWOULDBLOCK
|
// EWOULDBLOCK
|
||||||
return false;
|
return false;
|
||||||
@ -1048,18 +1054,17 @@ bool QProcessPrivate::tryReadFromChannel(Channel *channel)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (channel->closed) {
|
if (channel->closed) {
|
||||||
channel->buffer.chop(readBytes);
|
readBuffer.chop(readBytes);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
channel->buffer.chop(available - readBytes);
|
readBuffer.chop(available - readBytes);
|
||||||
|
|
||||||
bool didRead = false;
|
bool didRead = false;
|
||||||
bool isStdout = channel == &stdoutChannel;
|
|
||||||
if (readBytes == 0) {
|
if (readBytes == 0) {
|
||||||
if (channel->notifier)
|
if (channel->notifier)
|
||||||
channel->notifier->setEnabled(false);
|
channel->notifier->setEnabled(false);
|
||||||
} else if ((processChannel == QProcess::StandardOutput) == isStdout) {
|
} else if (currentReadChannel == channelIdx) {
|
||||||
didRead = true;
|
didRead = true;
|
||||||
if (!emittedReadyRead) {
|
if (!emittedReadyRead) {
|
||||||
emittedReadyRead = true;
|
emittedReadyRead = true;
|
||||||
@ -1067,7 +1072,8 @@ bool QProcessPrivate::tryReadFromChannel(Channel *channel)
|
|||||||
emittedReadyRead = false;
|
emittedReadyRead = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isStdout)
|
emit q->channelReadyRead(int(channelIdx));
|
||||||
|
if (channelIdx == QProcess::StandardOutput)
|
||||||
emit q->readyReadStandardOutput(QProcess::QPrivateSignal());
|
emit q->readyReadStandardOutput(QProcess::QPrivateSignal());
|
||||||
else
|
else
|
||||||
emit q->readyReadStandardError(QProcess::QPrivateSignal());
|
emit q->readyReadStandardError(QProcess::QPrivateSignal());
|
||||||
@ -1099,15 +1105,14 @@ bool QProcessPrivate::_q_canWrite()
|
|||||||
if (stdinChannel.notifier)
|
if (stdinChannel.notifier)
|
||||||
stdinChannel.notifier->setEnabled(false);
|
stdinChannel.notifier->setEnabled(false);
|
||||||
|
|
||||||
if (stdinChannel.buffer.isEmpty()) {
|
if (writeBuffer.isEmpty()) {
|
||||||
#if defined QPROCESS_DEBUG
|
#if defined QPROCESS_DEBUG
|
||||||
qDebug("QProcessPrivate::canWrite(), not writing anything (empty write buffer).");
|
qDebug("QProcessPrivate::canWrite(), not writing anything (empty write buffer).");
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 written = writeToStdin(stdinChannel.buffer.readPointer(),
|
qint64 written = writeToStdin(writeBuffer.readPointer(), writeBuffer.nextDataBlockSize());
|
||||||
stdinChannel.buffer.nextDataBlockSize());
|
|
||||||
if (written < 0) {
|
if (written < 0) {
|
||||||
closeChannel(&stdinChannel);
|
closeChannel(&stdinChannel);
|
||||||
setErrorAndEmit(QProcess::WriteError);
|
setErrorAndEmit(QProcess::WriteError);
|
||||||
@ -1119,16 +1124,17 @@ bool QProcessPrivate::_q_canWrite()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (written != 0) {
|
if (written != 0) {
|
||||||
stdinChannel.buffer.free(written);
|
writeBuffer.free(written);
|
||||||
if (!emittedBytesWritten) {
|
if (!emittedBytesWritten) {
|
||||||
emittedBytesWritten = true;
|
emittedBytesWritten = true;
|
||||||
emit q->bytesWritten(written);
|
emit q->bytesWritten(written);
|
||||||
emittedBytesWritten = false;
|
emittedBytesWritten = false;
|
||||||
}
|
}
|
||||||
|
emit q->channelBytesWritten(0, written);
|
||||||
}
|
}
|
||||||
if (stdinChannel.notifier && !stdinChannel.buffer.isEmpty())
|
if (stdinChannel.notifier && !writeBuffer.isEmpty())
|
||||||
stdinChannel.notifier->setEnabled(true);
|
stdinChannel.notifier->setEnabled(true);
|
||||||
if (stdinChannel.buffer.isEmpty() && stdinChannel.closed)
|
if (writeBuffer.isEmpty() && stdinChannel.closed)
|
||||||
closeWriteChannel();
|
closeWriteChannel();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1387,7 +1393,7 @@ void QProcess::setInputChannelMode(InputChannelMode mode)
|
|||||||
QProcess::ProcessChannel QProcess::readChannel() const
|
QProcess::ProcessChannel QProcess::readChannel() const
|
||||||
{
|
{
|
||||||
Q_D(const QProcess);
|
Q_D(const QProcess);
|
||||||
return d->processChannel;
|
return ProcessChannel(d->currentReadChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1400,20 +1406,7 @@ QProcess::ProcessChannel QProcess::readChannel() const
|
|||||||
*/
|
*/
|
||||||
void QProcess::setReadChannel(ProcessChannel channel)
|
void QProcess::setReadChannel(ProcessChannel channel)
|
||||||
{
|
{
|
||||||
Q_D(QProcess);
|
QIODevice::setCurrentReadChannel(int(channel));
|
||||||
|
|
||||||
if (d->transactionStarted) {
|
|
||||||
qWarning("QProcess::setReadChannel: Failed due to the active read transaction");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d->processChannel != channel) {
|
|
||||||
QRingBuffer *buffer = (d->processChannel == QProcess::StandardOutput)
|
|
||||||
? &d->stdoutChannel.buffer
|
|
||||||
: &d->stderrChannel.buffer;
|
|
||||||
d->buffer.read(buffer->reserveFront(d->buffer.size()), d->buffer.size());
|
|
||||||
}
|
|
||||||
d->processChannel = channel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1458,7 +1451,7 @@ void QProcess::closeWriteChannel()
|
|||||||
{
|
{
|
||||||
Q_D(QProcess);
|
Q_D(QProcess);
|
||||||
d->stdinChannel.closed = true; // closing
|
d->stdinChannel.closed = true; // closing
|
||||||
if (d->stdinChannel.buffer.isEmpty())
|
if (d->writeBuffer.isEmpty())
|
||||||
d->closeWriteChannel();
|
d->closeWriteChannel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1719,11 +1712,7 @@ qint64 QProcess::processId() const
|
|||||||
*/
|
*/
|
||||||
bool QProcess::canReadLine() const
|
bool QProcess::canReadLine() const
|
||||||
{
|
{
|
||||||
Q_D(const QProcess);
|
return QIODevice::canReadLine();
|
||||||
const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
|
|
||||||
? &d->stderrChannel.buffer
|
|
||||||
: &d->stdoutChannel.buffer;
|
|
||||||
return readBuffer->canReadLine() || QIODevice::canReadLine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1733,11 +1722,13 @@ bool QProcess::canReadLine() const
|
|||||||
*/
|
*/
|
||||||
void QProcess::close()
|
void QProcess::close()
|
||||||
{
|
{
|
||||||
|
Q_D(QProcess);
|
||||||
emit aboutToClose();
|
emit aboutToClose();
|
||||||
while (waitForBytesWritten(-1))
|
while (waitForBytesWritten(-1))
|
||||||
;
|
;
|
||||||
kill();
|
kill();
|
||||||
waitForFinished(-1);
|
waitForFinished(-1);
|
||||||
|
d->setWriteChannelCount(0);
|
||||||
QIODevice::close();
|
QIODevice::close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1748,11 +1739,7 @@ void QProcess::close()
|
|||||||
*/
|
*/
|
||||||
bool QProcess::atEnd() const
|
bool QProcess::atEnd() const
|
||||||
{
|
{
|
||||||
Q_D(const QProcess);
|
return QIODevice::atEnd();
|
||||||
const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
|
|
||||||
? &d->stderrChannel.buffer
|
|
||||||
: &d->stdoutChannel.buffer;
|
|
||||||
return QIODevice::atEnd() && (!isOpen() || readBuffer->isEmpty());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \reimp
|
/*! \reimp
|
||||||
@ -1766,25 +1753,16 @@ bool QProcess::isSequential() const
|
|||||||
*/
|
*/
|
||||||
qint64 QProcess::bytesAvailable() const
|
qint64 QProcess::bytesAvailable() const
|
||||||
{
|
{
|
||||||
Q_D(const QProcess);
|
return QIODevice::bytesAvailable();
|
||||||
const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
|
|
||||||
? &d->stderrChannel.buffer
|
|
||||||
: &d->stdoutChannel.buffer;
|
|
||||||
#if defined QPROCESS_DEBUG
|
|
||||||
qDebug("QProcess::bytesAvailable() == %i (%s)", readBuffer->size(),
|
|
||||||
(d->processChannel == QProcess::StandardError) ? "stderr" : "stdout");
|
|
||||||
#endif
|
|
||||||
return readBuffer->size() + QIODevice::bytesAvailable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \reimp
|
/*! \reimp
|
||||||
*/
|
*/
|
||||||
qint64 QProcess::bytesToWrite() const
|
qint64 QProcess::bytesToWrite() const
|
||||||
{
|
{
|
||||||
Q_D(const QProcess);
|
qint64 size = QIODevice::bytesToWrite();
|
||||||
qint64 size = d->stdinChannel.buffer.size();
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
size += d->pipeWriterBytesToWrite();
|
size += d_func()->pipeWriterBytesToWrite();
|
||||||
#endif
|
#endif
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@ -1923,9 +1901,9 @@ bool QProcess::waitForReadyRead(int msecs)
|
|||||||
|
|
||||||
if (d->processState == QProcess::NotRunning)
|
if (d->processState == QProcess::NotRunning)
|
||||||
return false;
|
return false;
|
||||||
if (d->processChannel == QProcess::StandardOutput && d->stdoutChannel.closed)
|
if (d->currentReadChannel == QProcess::StandardOutput && d->stdoutChannel.closed)
|
||||||
return false;
|
return false;
|
||||||
if (d->processChannel == QProcess::StandardError && d->stderrChannel.closed)
|
if (d->currentReadChannel == QProcess::StandardError && d->stderrChannel.closed)
|
||||||
return false;
|
return false;
|
||||||
return d->waitForReadyRead(msecs);
|
return d->waitForReadyRead(msecs);
|
||||||
}
|
}
|
||||||
@ -2024,47 +2002,12 @@ void QProcess::setupChildProcess()
|
|||||||
qint64 QProcess::readData(char *data, qint64 maxlen)
|
qint64 QProcess::readData(char *data, qint64 maxlen)
|
||||||
{
|
{
|
||||||
Q_D(QProcess);
|
Q_D(QProcess);
|
||||||
|
Q_UNUSED(data);
|
||||||
if (!maxlen)
|
if (!maxlen)
|
||||||
return 0;
|
return 0;
|
||||||
QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
|
if (d->processState == QProcess::NotRunning)
|
||||||
? &d->stderrChannel.buffer
|
|
||||||
: &d->stdoutChannel.buffer;
|
|
||||||
|
|
||||||
if (maxlen == 1 && !readBuffer->isEmpty()) {
|
|
||||||
int c = readBuffer->getChar();
|
|
||||||
if (c == -1) {
|
|
||||||
#if defined QPROCESS_DEBUG
|
|
||||||
qDebug("QProcess::readData(%p \"%s\", %d) == -1",
|
|
||||||
data, qt_prettyDebug(data, 1, maxlen).constData(), 1);
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*data = (char) c;
|
|
||||||
#if defined QPROCESS_DEBUG
|
|
||||||
qDebug("QProcess::readData(%p \"%s\", %d) == 1",
|
|
||||||
data, qt_prettyDebug(data, 1, maxlen).constData(), 1);
|
|
||||||
#endif
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
qint64 bytesToRead = qMin(readBuffer->size(), maxlen);
|
|
||||||
qint64 readSoFar = 0;
|
|
||||||
while (readSoFar < bytesToRead) {
|
|
||||||
const char *ptr = readBuffer->readPointer();
|
|
||||||
qint64 bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar,
|
|
||||||
readBuffer->nextDataBlockSize());
|
|
||||||
memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
|
|
||||||
readSoFar += bytesToReadFromThisBlock;
|
|
||||||
readBuffer->free(bytesToReadFromThisBlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined QPROCESS_DEBUG
|
|
||||||
qDebug("QProcess::readData(%p \"%s\", %lld) == %lld",
|
|
||||||
data, qt_prettyDebug(data, readSoFar, 16).constData(), maxlen, readSoFar);
|
|
||||||
#endif
|
|
||||||
if (!readSoFar && d->processState == QProcess::NotRunning)
|
|
||||||
return -1; // EOF
|
return -1; // EOF
|
||||||
return readSoFar;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \reimp
|
/*! \reimp
|
||||||
@ -2098,7 +2041,7 @@ qint64 QProcess::writeData(const char *data, qint64 len)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (len == 1) {
|
if (len == 1) {
|
||||||
d->stdinChannel.buffer.putChar(*data);
|
d->writeBuffer.putChar(*data);
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
if (!d->stdinWriteTrigger->isActive())
|
if (!d->stdinWriteTrigger->isActive())
|
||||||
d->stdinWriteTrigger->start();
|
d->stdinWriteTrigger->start();
|
||||||
@ -2113,7 +2056,7 @@ qint64 QProcess::writeData(const char *data, qint64 len)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *dest = d->stdinChannel.buffer.reserve(len);
|
char *dest = d->writeBuffer.reserve(len);
|
||||||
memcpy(dest, data, len);
|
memcpy(dest, data, len);
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
if (!d->stdinWriteTrigger->isActive())
|
if (!d->stdinWriteTrigger->isActive())
|
||||||
@ -2271,10 +2214,6 @@ void QProcessPrivate::start(QIODevice::OpenMode mode)
|
|||||||
qDebug() << "QProcess::start(" << program << ',' << arguments << ',' << mode << ')';
|
qDebug() << "QProcess::start(" << program << ',' << arguments << ',' << mode << ')';
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
stdinChannel.buffer.clear();
|
|
||||||
stdoutChannel.buffer.clear();
|
|
||||||
stderrChannel.buffer.clear();
|
|
||||||
|
|
||||||
if (stdinChannel.type != QProcessPrivate::Channel::Normal)
|
if (stdinChannel.type != QProcessPrivate::Channel::Normal)
|
||||||
mode &= ~QIODevice::WriteOnly; // not open for writing
|
mode &= ~QIODevice::WriteOnly; // not open for writing
|
||||||
if (stdoutChannel.type != QProcessPrivate::Channel::Normal &&
|
if (stdoutChannel.type != QProcessPrivate::Channel::Normal &&
|
||||||
@ -2295,6 +2234,9 @@ void QProcessPrivate::start(QIODevice::OpenMode mode)
|
|||||||
|
|
||||||
q->QIODevice::open(mode);
|
q->QIODevice::open(mode);
|
||||||
|
|
||||||
|
if (q->isReadable() && processChannelMode != QProcess::MergedChannels)
|
||||||
|
setReadChannelCount(2);
|
||||||
|
|
||||||
stdinChannel.closed = false;
|
stdinChannel.closed = false;
|
||||||
stdoutChannel.closed = false;
|
stdoutChannel.closed = false;
|
||||||
stderrChannel.closed = false;
|
stderrChannel.closed = false;
|
||||||
|
@ -235,12 +235,12 @@ public:
|
|||||||
QProcess::ExitStatus exitStatus() const;
|
QProcess::ExitStatus exitStatus() const;
|
||||||
|
|
||||||
// QIODevice
|
// QIODevice
|
||||||
qint64 bytesAvailable() const Q_DECL_OVERRIDE;
|
qint64 bytesAvailable() const Q_DECL_OVERRIDE; // ### Qt6: remove trivial override
|
||||||
qint64 bytesToWrite() const Q_DECL_OVERRIDE;
|
qint64 bytesToWrite() const Q_DECL_OVERRIDE;
|
||||||
bool isSequential() const Q_DECL_OVERRIDE;
|
bool isSequential() const Q_DECL_OVERRIDE;
|
||||||
bool canReadLine() const Q_DECL_OVERRIDE;
|
bool canReadLine() const Q_DECL_OVERRIDE; // ### Qt6: remove trivial override
|
||||||
void close() Q_DECL_OVERRIDE;
|
void close() Q_DECL_OVERRIDE;
|
||||||
bool atEnd() const Q_DECL_OVERRIDE;
|
bool atEnd() const Q_DECL_OVERRIDE; // ### Qt6: remove trivial override
|
||||||
|
|
||||||
static int execute(const QString &program, const QStringList &arguments);
|
static int execute(const QString &program, const QStringList &arguments);
|
||||||
static int execute(const QString &command);
|
static int execute(const QString &command);
|
||||||
|
@ -56,7 +56,6 @@
|
|||||||
#include "QtCore/qstringlist.h"
|
#include "QtCore/qstringlist.h"
|
||||||
#include "QtCore/qhash.h"
|
#include "QtCore/qhash.h"
|
||||||
#include "QtCore/qshareddata.h"
|
#include "QtCore/qshareddata.h"
|
||||||
#include "private/qringbuffer_p.h"
|
|
||||||
#include "private/qiodevice_p.h"
|
#include "private/qiodevice_p.h"
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
#include <QtCore/private/qorderedmutexlocker_p.h>
|
#include <QtCore/private/qorderedmutexlocker_p.h>
|
||||||
@ -293,7 +292,6 @@ public:
|
|||||||
QWindowsPipeWriter *writer;
|
QWindowsPipeWriter *writer;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
QRingBuffer buffer;
|
|
||||||
Q_PIPE pipe[2];
|
Q_PIPE pipe[2];
|
||||||
|
|
||||||
unsigned type : 2;
|
unsigned type : 2;
|
||||||
@ -311,7 +309,6 @@ public:
|
|||||||
bool _q_startupNotification();
|
bool _q_startupNotification();
|
||||||
bool _q_processDied();
|
bool _q_processDied();
|
||||||
|
|
||||||
QProcess::ProcessChannel processChannel;
|
|
||||||
QProcess::ProcessChannelMode processChannelMode;
|
QProcess::ProcessChannelMode processChannelMode;
|
||||||
QProcess::InputChannelMode inputChannelMode;
|
QProcess::InputChannelMode inputChannelMode;
|
||||||
QProcess::ProcessError processError;
|
QProcess::ProcessError processError;
|
||||||
|
@ -877,7 +877,7 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
|
|||||||
if (stderrChannel.pipe[0] != -1)
|
if (stderrChannel.pipe[0] != -1)
|
||||||
add_fd(nfds, stderrChannel.pipe[0], &fdread);
|
add_fd(nfds, stderrChannel.pipe[0], &fdread);
|
||||||
|
|
||||||
if (!stdinChannel.buffer.isEmpty() && stdinChannel.pipe[1] != -1)
|
if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
|
||||||
add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
|
add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
|
||||||
|
|
||||||
int timeout = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
|
int timeout = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
|
||||||
@ -899,12 +899,12 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
|
|||||||
bool readyReadEmitted = false;
|
bool readyReadEmitted = false;
|
||||||
if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) {
|
if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) {
|
||||||
bool canRead = _q_canReadStandardOutput();
|
bool canRead = _q_canReadStandardOutput();
|
||||||
if (processChannel == QProcess::StandardOutput && canRead)
|
if (currentReadChannel == QProcess::StandardOutput && canRead)
|
||||||
readyReadEmitted = true;
|
readyReadEmitted = true;
|
||||||
}
|
}
|
||||||
if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) {
|
if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) {
|
||||||
bool canRead = _q_canReadStandardError();
|
bool canRead = _q_canReadStandardError();
|
||||||
if (processChannel == QProcess::StandardError && canRead)
|
if (currentReadChannel == QProcess::StandardError && canRead)
|
||||||
readyReadEmitted = true;
|
readyReadEmitted = true;
|
||||||
}
|
}
|
||||||
if (readyReadEmitted)
|
if (readyReadEmitted)
|
||||||
@ -930,7 +930,7 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
|
|||||||
QElapsedTimer stopWatch;
|
QElapsedTimer stopWatch;
|
||||||
stopWatch.start();
|
stopWatch.start();
|
||||||
|
|
||||||
while (!stdinChannel.buffer.isEmpty()) {
|
while (!writeBuffer.isEmpty()) {
|
||||||
fd_set fdread;
|
fd_set fdread;
|
||||||
fd_set fdwrite;
|
fd_set fdwrite;
|
||||||
|
|
||||||
@ -949,7 +949,7 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
|
|||||||
add_fd(nfds, stderrChannel.pipe[0], &fdread);
|
add_fd(nfds, stderrChannel.pipe[0], &fdread);
|
||||||
|
|
||||||
|
|
||||||
if (!stdinChannel.buffer.isEmpty() && stdinChannel.pipe[1] != -1)
|
if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
|
||||||
add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
|
add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
|
||||||
|
|
||||||
int timeout = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
|
int timeout = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
|
||||||
@ -1015,7 +1015,7 @@ bool QProcessPrivate::waitForFinished(int msecs)
|
|||||||
if (processState == QProcess::Running && forkfd != -1)
|
if (processState == QProcess::Running && forkfd != -1)
|
||||||
add_fd(nfds, forkfd, &fdread);
|
add_fd(nfds, forkfd, &fdread);
|
||||||
|
|
||||||
if (!stdinChannel.buffer.isEmpty() && stdinChannel.pipe[1] != -1)
|
if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
|
||||||
add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
|
add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
|
||||||
|
|
||||||
int timeout = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
|
int timeout = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
|
||||||
|
@ -652,7 +652,7 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
|
|||||||
QIncrementalSleepTimer timer(msecs);
|
QIncrementalSleepTimer timer(msecs);
|
||||||
|
|
||||||
forever {
|
forever {
|
||||||
if (!stdinChannel.buffer.isEmpty() && !_q_canWrite())
|
if (!writeBuffer.isEmpty() && !_q_canWrite())
|
||||||
return false;
|
return false;
|
||||||
if (stdinChannel.writer && stdinChannel.writer->waitForWrite(0))
|
if (stdinChannel.writer && stdinChannel.writer->waitForWrite(0))
|
||||||
timer.resetIncrements();
|
timer.resetIncrements();
|
||||||
@ -690,7 +690,7 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
|
|||||||
|
|
||||||
// If we don't have pending data, and our write buffer is
|
// If we don't have pending data, and our write buffer is
|
||||||
// empty, we fail.
|
// empty, we fail.
|
||||||
if (!pendingDataInPipe && stdinChannel.buffer.isEmpty())
|
if (!pendingDataInPipe && writeBuffer.isEmpty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// If we don't have pending data and we do have data in our
|
// If we don't have pending data and we do have data in our
|
||||||
@ -754,7 +754,7 @@ bool QProcessPrivate::waitForFinished(int msecs)
|
|||||||
QIncrementalSleepTimer timer(msecs);
|
QIncrementalSleepTimer timer(msecs);
|
||||||
|
|
||||||
forever {
|
forever {
|
||||||
if (!stdinChannel.buffer.isEmpty() && !_q_canWrite())
|
if (!writeBuffer.isEmpty() && !_q_canWrite())
|
||||||
return false;
|
return false;
|
||||||
if (stdinChannel.writer && stdinChannel.writer->waitForWrite(0))
|
if (stdinChannel.writer && stdinChannel.writer->waitForWrite(0))
|
||||||
timer.resetIncrements();
|
timer.resetIncrements();
|
||||||
|
@ -56,10 +56,14 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
#ifndef QRINGBUFFER_CHUNKSIZE
|
||||||
|
#define QRINGBUFFER_CHUNKSIZE 4096
|
||||||
|
#endif
|
||||||
|
|
||||||
class QRingBuffer
|
class QRingBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit inline QRingBuffer(int growth = 4096) :
|
explicit inline QRingBuffer(int growth = QRINGBUFFER_CHUNKSIZE) :
|
||||||
head(0), tail(0), tailBuffer(0), basicBlockSize(growth), bufferSize(0) { }
|
head(0), tail(0), tailBuffer(0), basicBlockSize(growth), bufferSize(0) { }
|
||||||
|
|
||||||
inline qint64 nextDataBlockSize() const {
|
inline qint64 nextDataBlockSize() const {
|
||||||
|
@ -493,9 +493,11 @@ void tst_QProcess::echoTest2()
|
|||||||
QCOMPARE(process.error(), QProcess::Timedout);
|
QCOMPARE(process.error(), QProcess::Timedout);
|
||||||
|
|
||||||
process.write("Hello");
|
process.write("Hello");
|
||||||
|
QSignalSpy spy0(&process, &QProcess::channelReadyRead);
|
||||||
QSignalSpy spy1(&process, &QProcess::readyReadStandardOutput);
|
QSignalSpy spy1(&process, &QProcess::readyReadStandardOutput);
|
||||||
QSignalSpy spy2(&process, &QProcess::readyReadStandardError);
|
QSignalSpy spy2(&process, &QProcess::readyReadStandardError);
|
||||||
|
|
||||||
|
QVERIFY(spy0.isValid());
|
||||||
QVERIFY(spy1.isValid());
|
QVERIFY(spy1.isValid());
|
||||||
QVERIFY(spy2.isValid());
|
QVERIFY(spy2.isValid());
|
||||||
|
|
||||||
@ -514,6 +516,7 @@ void tst_QProcess::echoTest2()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVERIFY(spy0.count() > 0);
|
||||||
QVERIFY(spy1.count() > 0);
|
QVERIFY(spy1.count() > 0);
|
||||||
QVERIFY(spy2.count() > 0);
|
QVERIFY(spy2.count() > 0);
|
||||||
|
|
||||||
@ -985,6 +988,9 @@ public:
|
|||||||
this, &SoftExitProcess::terminateSlot);
|
this, &SoftExitProcess::terminateSlot);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
|
setReadChannelMode(QProcess::MergedChannels);
|
||||||
|
connect(this, SIGNAL(channelReadyRead(int)), this, SLOT(terminateSlot()));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
connect(this, &QProcess::stateChanged,
|
connect(this, &QProcess::stateChanged,
|
||||||
this, &SoftExitProcess::terminateSlot);
|
this, &SoftExitProcess::terminateSlot);
|
||||||
@ -1057,7 +1063,7 @@ void tst_QProcess::softExitInSlots()
|
|||||||
{
|
{
|
||||||
QFETCH(QString, appName);
|
QFETCH(QString, appName);
|
||||||
|
|
||||||
for (int i = 0; i < 5; ++i) {
|
for (int i = 0; i < 6; ++i) {
|
||||||
SoftExitProcess proc(i);
|
SoftExitProcess proc(i);
|
||||||
proc.writeAfterStart("OLEBOLE", 8); // include the \0
|
proc.writeAfterStart("OLEBOLE", 8); // include the \0
|
||||||
proc.start(appName);
|
proc.start(appName);
|
||||||
|
Loading…
Reference in New Issue
Block a user