summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@digia.com>2014-07-01 10:03:53 +0200
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2014-07-01 16:25:19 +0200
commita09a8d509a69ed16d8afbe15296b8332cacd6c66 (patch)
tree28645b437fd0390d903f753a44ba79626eecb8ac /src/corelib/io
parent4b28152da64f7f23a1bbb810d8cdb7626a5f0b8e (diff)
parent83f06da1c6bffff61af78cbe75a0691d53742b53 (diff)
Merge remote-tracking branch 'origin/5.3' into dev
Conflicts: mkspecs/qnx-x86-qcc/qplatformdefs.h src/corelib/global/qglobal.h src/network/socket/qnativesocketengine_winrt.cpp src/plugins/platforms/android/androidjniaccessibility.cpp src/plugins/platforms/windows/qwindowswindow.cpp Manually adjusted: mkspecs/qnx-armle-v7-qcc/qplatformdefs.h to include 9ce697f2d54be6d94381c72af28dda79cbc027d4 Thanks goes to Sergio for the qnx mkspecs adjustments. Change-Id: I53b1fd6bc5bc884e5ee2c2b84975f58171a1cb8e
Diffstat (limited to 'src/corelib/io')
-rw-r--r--src/corelib/io/qfileinfo.cpp7
-rw-r--r--src/corelib/io/qfilesystemwatcher_fsevents.mm28
-rw-r--r--src/corelib/io/qloggingcategory.cpp40
-rw-r--r--src/corelib/io/qloggingcategory.h35
-rw-r--r--src/corelib/io/qprocess.cpp164
-rw-r--r--src/corelib/io/qprocess_p.h28
-rw-r--r--src/corelib/io/qprocess_unix.cpp59
-rw-r--r--src/corelib/io/qprocess_win.cpp160
-rw-r--r--src/corelib/io/qprocess_wince.cpp16
-rw-r--r--src/corelib/io/qstandardpaths_winrt.cpp19
-rw-r--r--src/corelib/io/qwindowspipereader.cpp4
11 files changed, 281 insertions, 279 deletions
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index 60f7e47e62..210bb3898c 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -530,7 +530,8 @@ void QFileInfo::setFile(const QDir &dir, const QString &file)
is true. In contrast to canonicalFilePath(), symbolic links or
redundant "." or ".." elements are not necessarily removed.
- If the QFileInfo is empty it returns QDir::currentPath().
+ \warning If filePath() is empty the behavior of this function
+ is undefined.
\sa filePath(), canonicalFilePath(), isRelative()
*/
@@ -572,8 +573,8 @@ QString QFileInfo::canonicalFilePath() const
In contrast to canonicalPath() symbolic links or redundant "." or
".." elements are not necessarily removed.
- \warning If the QFileInfo object was created with an empty QString,
- the behavior of this function is undefined.
+ \warning If filePath() is empty the behavior of this function
+ is undefined.
\sa absoluteFilePath(), path(), canonicalPath(), fileName(), isRelative()
*/
diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.mm b/src/corelib/io/qfilesystemwatcher_fsevents.mm
index 981d663694..085396da6d 100644
--- a/src/corelib/io/qfilesystemwatcher_fsevents.mm
+++ b/src/corelib/io/qfilesystemwatcher_fsevents.mm
@@ -64,6 +64,25 @@
QT_BEGIN_NAMESPACE
+namespace {
+class RaiiAutoreleasePool
+{
+ Q_DISABLE_COPY(RaiiAutoreleasePool)
+
+public:
+ RaiiAutoreleasePool()
+ : pool([[NSAutoreleasePool alloc] init])
+ {}
+
+ ~RaiiAutoreleasePool()
+ { [pool release]; }
+
+private:
+ NSAutoreleasePool *pool;
+};
+#define Q_AUTORELEASE_POOL(pool) RaiiAutoreleasePool pool; Q_UNUSED(pool);
+}
+
static void callBackFunction(ConstFSEventStreamRef streamRef,
void *clientCallBackInfo,
size_t numEvents,
@@ -71,6 +90,8 @@ static void callBackFunction(ConstFSEventStreamRef streamRef,
const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[])
{
+ Q_AUTORELEASE_POOL(pool)
+
char **paths = static_cast<char **>(eventPaths);
QFseventsFileSystemWatcherEngine *engine = static_cast<QFseventsFileSystemWatcherEngine *>(clientCallBackInfo);
engine->processEvent(streamRef, numEvents, paths, eventFlags, eventIds);
@@ -283,6 +304,7 @@ void QFseventsFileSystemWatcherEngine::doEmitDirectoryChanged(const QString path
void QFseventsFileSystemWatcherEngine::restartStream()
{
+ Q_AUTORELEASE_POOL(pool)
QMutexLocker locker(&lock);
stopStream();
startStream();
@@ -313,6 +335,8 @@ QFseventsFileSystemWatcherEngine::QFseventsFileSystemWatcherEngine(QObject *pare
QFseventsFileSystemWatcherEngine::~QFseventsFileSystemWatcherEngine()
{
+ Q_AUTORELEASE_POOL(pool)
+
if (stream)
FSEventStreamStop(stream);
@@ -327,6 +351,8 @@ QStringList QFseventsFileSystemWatcherEngine::addPaths(const QStringList &paths,
QStringList *files,
QStringList *directories)
{
+ Q_AUTORELEASE_POOL(pool)
+
if (stream) {
DEBUG("Flushing, last id is %llu", FSEventStreamGetLatestEventId(stream));
FSEventStreamFlushSync(stream);
@@ -413,6 +439,8 @@ QStringList QFseventsFileSystemWatcherEngine::removePaths(const QStringList &pat
QStringList *files,
QStringList *directories)
{
+ Q_AUTORELEASE_POOL(pool)
+
QMutexLocker locker(&lock);
bool needsRestart = false;
diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp
index 518052e537..07245ddea2 100644
--- a/src/corelib/io/qloggingcategory.cpp
+++ b/src/corelib/io/qloggingcategory.cpp
@@ -50,6 +50,18 @@ const char qtDefaultCategoryName[] = "default";
Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
(qtDefaultCategoryName))
+#ifndef Q_ATOMIC_INT8_IS_SUPPORTED
+static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
+{
+ const int bit = 1 << shift;
+
+ if (enable)
+ atomic->fetchAndOrRelaxed(bit);
+ else
+ atomic->fetchAndAndRelaxed(~bit);
+}
+#endif
+
/*!
\class QLoggingCategory
\inmodule QtCore
@@ -129,13 +141,13 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
Order of evaluation:
\list
- \li Rules from QtProject/qlogging.ini
+ \li Rules from QtProject/qtlogging.ini
\li Rules set by \l setFilterRules()
\li Rules from file in \c QT_LOGGING_CONF
\li Rules from environment variable QT_LOGGING_RULES
\endlist
- The \c QtProject/qlogging.ini file is looked up in all directories returned
+ The \c QtProject/qtlogging.ini file is looked up in all directories returned
by QStandardPaths::GenericConfigLocation, e.g.
\list
@@ -171,13 +183,11 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
*/
QLoggingCategory::QLoggingCategory(const char *category)
: d(0),
- name(0),
- enabledDebug(true),
- enabledWarning(true),
- enabledCritical(true)
+ name(0)
{
Q_UNUSED(d);
Q_UNUSED(placeholder);
+ enabled.store(0x01010101); // enabledDebug = enabledWarning = enabledCritical = true;
const bool isDefaultCategory
= (category == 0) || (strcmp(category, qtDefaultCategoryName) == 0);
@@ -249,9 +259,9 @@ QLoggingCategory::~QLoggingCategory()
bool QLoggingCategory::isEnabled(QtMsgType msgtype) const
{
switch (msgtype) {
- case QtDebugMsg: return enabledDebug;
- case QtWarningMsg: return enabledWarning;
- case QtCriticalMsg: return enabledCritical;
+ case QtDebugMsg: return isDebugEnabled();
+ case QtWarningMsg: return isWarningEnabled();
+ case QtCriticalMsg: return isCriticalEnabled();
case QtFatalMsg: return true;
}
return false;
@@ -270,9 +280,15 @@ bool QLoggingCategory::isEnabled(QtMsgType msgtype) const
void QLoggingCategory::setEnabled(QtMsgType type, bool enable)
{
switch (type) {
- case QtDebugMsg: enabledDebug = enable; break;
- case QtWarningMsg: enabledWarning = enable; break;
- case QtCriticalMsg: enabledCritical = enable; break;
+#ifdef Q_ATOMIC_INT8_IS_SUPPORTED
+ case QtDebugMsg: bools.enabledDebug.store(enable); break;
+ case QtWarningMsg: bools.enabledWarning.store(enable); break;
+ case QtCriticalMsg: bools.enabledCritical.store(enable); break;
+#else
+ case QtDebugMsg: setBoolLane(&enabled, enable, DebugShift); break;
+ case QtWarningMsg: setBoolLane(&enabled, enable, WarningShift); break;
+ case QtCriticalMsg: setBoolLane(&enabled, enable, CriticalShift); break;
+#endif
case QtFatalMsg: break;
}
}
diff --git a/src/corelib/io/qloggingcategory.h b/src/corelib/io/qloggingcategory.h
index 4aec8e63bf..573af2105c 100644
--- a/src/corelib/io/qloggingcategory.h
+++ b/src/corelib/io/qloggingcategory.h
@@ -57,10 +57,15 @@ public:
bool isEnabled(QtMsgType type) const;
void setEnabled(QtMsgType type, bool enable);
- bool isDebugEnabled() const { return enabledDebug; }
- bool isWarningEnabled() const { return enabledWarning; }
- bool isCriticalEnabled() const { return enabledCritical; }
-
+#ifdef Q_ATOMIC_INT8_IS_SUPPORTED
+ bool isDebugEnabled() const { return bools.enabledDebug.load(); }
+ bool isWarningEnabled() const { return bools.enabledWarning.load(); }
+ bool isCriticalEnabled() const { return bools.enabledCritical.load(); }
+#else
+ bool isDebugEnabled() const { return enabled.load() >> DebugShift & 1; }
+ bool isWarningEnabled() const { return enabled.load() >> WarningShift & 1; }
+ bool isCriticalEnabled() const { return enabled.load() >> CriticalShift & 1; }
+#endif
const char *categoryName() const { return name; }
// allows usage of both factory method and variable in qCX macros
@@ -78,10 +83,24 @@ private:
void *d; // reserved for future use
const char *name;
- bool enabledDebug;
- bool enabledWarning;
- bool enabledCritical;
- bool placeholder[5]; // reserve for future use
+#ifdef Q_BIG_ENDIAN
+ enum { DebugShift = 0, WarningShift = 8, CriticalShift = 16 };
+#else
+ enum { DebugShift = 24, WarningShift = 16, CriticalShift = 8 };
+#endif
+
+ struct AtomicBools {
+#ifdef Q_ATOMIC_INT8_IS_SUPPORTED
+ QBasicAtomicInteger<bool> enabledDebug;
+ QBasicAtomicInteger<bool> enabledWarning;
+ QBasicAtomicInteger<bool> enabledCritical;
+#endif
+ };
+ union {
+ AtomicBools bools;
+ QBasicAtomicInt enabled;
+ };
+ bool placeholder[4]; // reserve for future use
};
#define Q_DECLARE_LOGGING_CATEGORY(name) \
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index 9f9cba81ab..b03e96d0f6 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Intel Corporation
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -819,9 +820,6 @@ QProcessPrivate::QProcessPrivate()
emittedBytesWritten = false;
#ifdef Q_OS_WIN
notifier = 0;
- stdoutReader = 0;
- stderrReader = 0;
- pipeWriter = 0;
processFinishedNotifier = 0;
#endif // Q_OS_WIN
#ifdef Q_OS_UNIX
@@ -889,9 +887,9 @@ void QProcessPrivate::cleanup()
notifier = 0;
}
#endif
- destroyChannel(&stdoutChannel);
- destroyChannel(&stderrChannel);
- destroyChannel(&stdinChannel);
+ closeChannel(&stdoutChannel);
+ closeChannel(&stderrChannel);
+ closeChannel(&stdinChannel);
destroyPipe(childStartedPipe);
destroyPipe(deathPipe);
#ifdef Q_OS_UNIX
@@ -901,49 +899,63 @@ void QProcessPrivate::cleanup()
/*!
\internal
+ Returns true if we emitted readyRead().
*/
-bool QProcessPrivate::_q_canReadStandardOutput()
+bool QProcessPrivate::tryReadFromChannel(Channel *channel)
{
Q_Q(QProcess);
- qint64 available = bytesAvailableFromStdout();
- if (available == 0) {
- if (stdoutChannel.notifier)
- stdoutChannel.notifier->setEnabled(false);
- destroyChannel(&stdoutChannel);
-#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::canReadStandardOutput(), 0 bytes available");
-#endif
+ if (channel->pipe[0] == INVALID_Q_PIPE)
return false;
- }
- char *ptr = outputReadBuffer.reserve(available);
- qint64 readBytes = readFromStdout(ptr, available);
+ qint64 available = bytesAvailableInChannel(channel);
+ if (available == 0)
+ available = 1; // always try to read at least one byte
+
+ char *ptr = channel->buffer.reserve(available);
+ qint64 readBytes = readFromChannel(channel, ptr, available);
+ if (readBytes <= 0)
+ channel->buffer.chop(available);
+ if (readBytes == -2) {
+ // EWOULDBLOCK
+ return false;
+ }
if (readBytes == -1) {
processError = QProcess::ReadError;
q->setErrorString(QProcess::tr("Error reading from process"));
emit q->error(processError);
#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::canReadStandardOutput(), failed to read from the process");
+ qDebug("QProcessPrivate::tryReadFromChannel(%d), failed to read from the process", channel - &stdinChannel);
+#endif
+ return false;
+ }
+ if (readBytes == 0) {
+ // EOF
+ if (channel->notifier)
+ channel->notifier->setEnabled(false);
+ closeChannel(channel);
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::tryReadFromChannel(%d), 0 bytes available", channel - &stdinChannel);
#endif
return false;
}
#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::canReadStandardOutput(), read %d bytes from the process' output",
+ qDebug("QProcessPrivate::tryReadFromChannel(%d), read %d bytes from the process' output", channel - &stdinChannel
int(readBytes));
#endif
- if (stdoutChannel.closed) {
- outputReadBuffer.chop(readBytes);
+ if (channel->closed) {
+ channel->buffer.chop(readBytes);
return false;
}
- outputReadBuffer.chop(available - readBytes);
+ channel->buffer.chop(available - readBytes);
bool didRead = false;
+ bool isStdout = channel == &stdoutChannel;
if (readBytes == 0) {
- if (stdoutChannel.notifier)
- stdoutChannel.notifier->setEnabled(false);
- } else if (processChannel == QProcess::StandardOutput) {
+ if (channel->notifier)
+ channel->notifier->setEnabled(false);
+ } else if ((processChannel == QProcess::StandardOutput) == isStdout) {
didRead = true;
if (!emittedReadyRead) {
emittedReadyRead = true;
@@ -951,53 +963,27 @@ bool QProcessPrivate::_q_canReadStandardOutput()
emittedReadyRead = false;
}
}
- emit q->readyReadStandardOutput(QProcess::QPrivateSignal());
+ if (isStdout)
+ emit q->readyReadStandardOutput(QProcess::QPrivateSignal());
+ else
+ emit q->readyReadStandardError(QProcess::QPrivateSignal());
return didRead;
}
/*!
\internal
*/
-bool QProcessPrivate::_q_canReadStandardError()
+bool QProcessPrivate::_q_canReadStandardOutput()
{
- Q_Q(QProcess);
- qint64 available = bytesAvailableFromStderr();
- if (available == 0) {
- if (stderrChannel.notifier)
- stderrChannel.notifier->setEnabled(false);
- destroyChannel(&stderrChannel);
- return false;
- }
-
- char *ptr = errorReadBuffer.reserve(available);
- qint64 readBytes = readFromStderr(ptr, available);
- if (readBytes == -1) {
- processError = QProcess::ReadError;
- q->setErrorString(QProcess::tr("Error reading from process"));
- emit q->error(processError);
- return false;
- }
- if (stderrChannel.closed) {
- errorReadBuffer.chop(readBytes);
- return false;
- }
-
- errorReadBuffer.chop(available - readBytes);
+ return tryReadFromChannel(&stdoutChannel);
+}
- bool didRead = false;
- if (readBytes == 0) {
- if (stderrChannel.notifier)
- stderrChannel.notifier->setEnabled(false);
- } else if (processChannel == QProcess::StandardError) {
- didRead = true;
- if (!emittedReadyRead) {
- emittedReadyRead = true;
- emit q->readyRead();
- emittedReadyRead = false;
- }
- }
- emit q->readyReadStandardError(QProcess::QPrivateSignal());
- return didRead;
+/*!
+ \internal
+*/
+bool QProcessPrivate::_q_canReadStandardError()
+{
+ return tryReadFromChannel(&stderrChannel);
}
/*!
@@ -1009,17 +995,17 @@ bool QProcessPrivate::_q_canWrite()
if (stdinChannel.notifier)
stdinChannel.notifier->setEnabled(false);
- if (writeBuffer.isEmpty()) {
+ if (stdinChannel.buffer.isEmpty()) {
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::canWrite(), not writing anything (empty write buffer).");
#endif
return false;
}
- qint64 written = writeToStdin(writeBuffer.readPointer(),
- writeBuffer.nextDataBlockSize());
+ qint64 written = writeToStdin(stdinChannel.buffer.readPointer(),
+ stdinChannel.buffer.nextDataBlockSize());
if (written < 0) {
- destroyChannel(&stdinChannel);
+ closeChannel(&stdinChannel);
processError = QProcess::WriteError;
q->setErrorString(QProcess::tr("Error writing to process"));
emit q->error(processError);
@@ -1031,16 +1017,16 @@ bool QProcessPrivate::_q_canWrite()
#endif
if (written != 0) {
- writeBuffer.free(written);
+ stdinChannel.buffer.free(written);
if (!emittedBytesWritten) {
emittedBytesWritten = true;
emit q->bytesWritten(written);
emittedBytesWritten = false;
}
}
- if (stdinChannel.notifier && !writeBuffer.isEmpty())
+ if (stdinChannel.notifier && !stdinChannel.buffer.isEmpty())
stdinChannel.notifier->setEnabled(true);
- if (writeBuffer.isEmpty() && stdinChannel.closed)
+ if (stdinChannel.buffer.isEmpty() && stdinChannel.closed)
closeWriteChannel();
return true;
}
@@ -1163,7 +1149,7 @@ void QProcessPrivate::closeWriteChannel()
// instead.
flushPipeWriter();
#endif
- destroyChannel(&stdinChannel);
+ closeChannel(&stdinChannel);
}
/*!
@@ -1308,10 +1294,10 @@ void QProcess::setReadChannel(ProcessChannel channel)
QByteArray buf = d->buffer.readAll();
if (d->processChannel == QProcess::StandardOutput) {
for (int i = buf.size() - 1; i >= 0; --i)
- d->outputReadBuffer.ungetChar(buf.at(i));
+ d->stdoutChannel.buffer.ungetChar(buf.at(i));
} else {
for (int i = buf.size() - 1; i >= 0; --i)
- d->errorReadBuffer.ungetChar(buf.at(i));
+ d->stderrChannel.buffer.ungetChar(buf.at(i));
}
}
d->processChannel = channel;
@@ -1359,7 +1345,7 @@ void QProcess::closeWriteChannel()
{
Q_D(QProcess);
d->stdinChannel.closed = true; // closing
- if (d->writeBuffer.isEmpty())
+ if (d->stdinChannel.buffer.isEmpty())
d->closeWriteChannel();
}
@@ -1589,8 +1575,8 @@ bool QProcess::canReadLine() const
{
Q_D(const QProcess);
const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
- ? &d->errorReadBuffer
- : &d->outputReadBuffer;
+ ? &d->stderrChannel.buffer
+ : &d->stdoutChannel.buffer;
return readBuffer->canReadLine() || QIODevice::canReadLine();
}
@@ -1618,8 +1604,8 @@ bool QProcess::atEnd() const
{
Q_D(const QProcess);
const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
- ? &d->errorReadBuffer
- : &d->outputReadBuffer;
+ ? &d->stderrChannel.buffer
+ : &d->stdoutChannel.buffer;
return QIODevice::atEnd() && (!isOpen() || readBuffer->isEmpty());
}
@@ -1636,8 +1622,8 @@ qint64 QProcess::bytesAvailable() const
{
Q_D(const QProcess);
const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
- ? &d->errorReadBuffer
- : &d->outputReadBuffer;
+ ? &d->stderrChannel.buffer
+ : &d->stdoutChannel.buffer;
#if defined QPROCESS_DEBUG
qDebug("QProcess::bytesAvailable() == %i (%s)", readBuffer->size(),
(d->processChannel == QProcess::StandardError) ? "stderr" : "stdout");
@@ -1650,7 +1636,7 @@ qint64 QProcess::bytesAvailable() const
qint64 QProcess::bytesToWrite() const
{
Q_D(const QProcess);
- qint64 size = d->writeBuffer.size();
+ qint64 size = d->stdinChannel.buffer.size();
#ifdef Q_OS_WIN
size += d->pipeWriterBytesToWrite();
#endif
@@ -1897,8 +1883,8 @@ qint64 QProcess::readData(char *data, qint64 maxlen)
if (!maxlen)
return 0;
QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
- ? &d->errorReadBuffer
- : &d->outputReadBuffer;
+ ? &d->stderrChannel.buffer
+ : &d->stdoutChannel.buffer;
if (maxlen == 1 && !readBuffer->isEmpty()) {
int c = readBuffer->getChar();
@@ -1961,7 +1947,7 @@ qint64 QProcess::writeData(const char *data, qint64 len)
}
if (len == 1) {
- d->writeBuffer.putChar(*data);
+ d->stdinChannel.buffer.putChar(*data);
if (d->stdinChannel.notifier)
d->stdinChannel.notifier->setEnabled(true);
#if defined QPROCESS_DEBUG
@@ -1971,7 +1957,7 @@ qint64 QProcess::writeData(const char *data, qint64 len)
return 1;
}
- char *dest = d->writeBuffer.reserve(len);
+ char *dest = d->stdinChannel.buffer.reserve(len);
memcpy(dest, data, len);
if (d->stdinChannel.notifier)
d->stdinChannel.notifier->setEnabled(true);
@@ -2112,8 +2098,8 @@ void QProcessPrivate::start(QIODevice::OpenMode mode)
qDebug() << "QProcess::start(" << program << ',' << arguments << ',' << mode << ')';
#endif
- outputReadBuffer.clear();
- errorReadBuffer.clear();
+ stdoutChannel.buffer.clear();
+ stderrChannel.buffer.clear();
if (stdinChannel.type != QProcessPrivate::Channel::Normal)
mode &= ~QIODevice::WriteOnly; // not open for writing
diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h
index 5d65b2a068..6cd9047c04 100644
--- a/src/corelib/io/qprocess_p.h
+++ b/src/corelib/io/qprocess_p.h
@@ -253,6 +253,9 @@ public:
{
pipe[0] = INVALID_Q_PIPE;
pipe[1] = INVALID_Q_PIPE;
+#ifdef Q_OS_WIN
+ reader = 0;
+#endif
}
void clear();
@@ -282,6 +285,13 @@ public:
QString file;
QProcessPrivate *process;
QSocketNotifier *notifier;
+#ifdef Q_OS_WIN
+ union {
+ QWindowsPipeReader *reader;
+ QWindowsPipeWriter *writer;
+ };
+#endif
+ QRingBuffer buffer;
Q_PIPE pipe[2];
unsigned type : 2;
@@ -316,8 +326,10 @@ public:
Channel stdinChannel;
Channel stdoutChannel;
Channel stderrChannel;
- bool createChannel(Channel &channel);
+ bool openChannel(Channel &channel);
+ void closeChannel(Channel *channel);
void closeWriteChannel();
+ bool tryReadFromChannel(Channel *channel); // obviously, only stdout and stderr
QString program;
QStringList arguments;
@@ -326,14 +338,9 @@ public:
#endif
QProcessEnvironment environment;
- QRingBuffer outputReadBuffer;
- QRingBuffer errorReadBuffer;
- QRingBuffer writeBuffer;
-
Q_PIPE childStartedPipe[2];
Q_PIPE deathPipe[2];
void destroyPipe(Q_PIPE pipe[2]);
- void destroyChannel(Channel *channel);
QSocketNotifier *startupSocketNotifier;
QSocketNotifier *deathNotifier;
@@ -341,9 +348,6 @@ public:
#ifdef Q_OS_WIN
// the wonderful windows notifier
QTimer *notifier;
- QWindowsPipeReader *stdoutReader;
- QWindowsPipeReader *stderrReader;
- QWindowsPipeWriter *pipeWriter;
QWinEventNotifier *processFinishedNotifier;
#endif
@@ -383,10 +387,8 @@ public:
bool waitForFinished(int msecs = 30000);
bool waitForWrite(int msecs = 30000);
- qint64 bytesAvailableFromStdout() const;
- qint64 bytesAvailableFromStderr() const;
- qint64 readFromStdout(char *data, qint64 maxlen);
- qint64 readFromStderr(char *data, qint64 maxlen);
+ qint64 bytesAvailableInChannel(const Channel *channel) const;
+ qint64 readFromChannel(const Channel *channel, char *data, qint64 maxlen);
qint64 writeToStdin(const char *data, qint64 maxlen);
void cleanup();
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 8674371baa..2269740a2f 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -377,7 +377,7 @@ void QProcessPrivate::destroyPipe(int *pipe)
}
}
-void QProcessPrivate::destroyChannel(Channel *channel)
+void QProcessPrivate::closeChannel(Channel *channel)
{
destroyPipe(channel->pipe);
}
@@ -387,7 +387,7 @@ void QProcessPrivate::destroyChannel(Channel *channel)
This function must be called in order: stdin, stdout, stderr
*/
-bool QProcessPrivate::createChannel(Channel &channel)
+bool QProcessPrivate::openChannel(Channel &channel)
{
Q_Q(QProcess);
@@ -573,9 +573,9 @@ void QProcessPrivate::startProcess()
processManager()->start();
// Initialize pipes
- if (!createChannel(stdinChannel) ||
- !createChannel(stdoutChannel) ||
- !createChannel(stderrChannel) ||
+ if (!openChannel(stdinChannel) ||
+ !openChannel(stdoutChannel) ||
+ !openChannel(stderrChannel) ||
qt_create_pipe(childStartedPipe) != 0 ||
qt_create_pipe(deathPipe) != 0) {
processError = QProcess::FailedToStart;
@@ -963,47 +963,32 @@ bool QProcessPrivate::processStarted()
return i <= 0;
}
-qint64 QProcessPrivate::bytesAvailableFromStdout() const
+qint64 QProcessPrivate::bytesAvailableInChannel(const Channel *channel) const
{
+ Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE);
int nbytes = 0;
qint64 available = 0;
- if (::ioctl(stdoutChannel.pipe[0], FIONREAD, (char *) &nbytes) >= 0)
+ if (::ioctl(channel->pipe[0], FIONREAD, (char *) &nbytes) >= 0)
available = (qint64) nbytes;
#if defined (QPROCESS_DEBUG)
- qDebug("QProcessPrivate::bytesAvailableFromStdout() == %lld", available);
+ qDebug("QProcessPrivate::bytesAvailableInChannel(%d) == %lld", channel - &stdinChannel, available);
#endif
return available;
}
-qint64 QProcessPrivate::bytesAvailableFromStderr() const
+qint64 QProcessPrivate::readFromChannel(const Channel *channel, char *data, qint64 maxlen)
{
- int nbytes = 0;
- qint64 available = 0;
- if (::ioctl(stderrChannel.pipe[0], FIONREAD, (char *) &nbytes) >= 0)
- available = (qint64) nbytes;
-#if defined (QPROCESS_DEBUG)
- qDebug("QProcessPrivate::bytesAvailableFromStderr() == %lld", available);
-#endif
- return available;
-}
-
-qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen)
-{
- qint64 bytesRead = qt_safe_read(stdoutChannel.pipe[0], data, maxlen);
-#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::readFromStdout(%p \"%s\", %lld) == %lld",
- data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead);
-#endif
- return bytesRead;
-}
-
-qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen)
-{
- qint64 bytesRead = qt_safe_read(stderrChannel.pipe[0], data, maxlen);
+ Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE);
+ qint64 bytesRead = qt_safe_read(channel->pipe[0], data, maxlen);
#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::readFromStderr(%p \"%s\", %lld) == %lld",
+ int save_errno = errno;
+ qDebug("QProcessPrivate::readFromChannel(%d, %p \"%s\", %lld) == %lld",
+ channel - &stdinChannel,
data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead);
+ errno = save_errno;
#endif
+ if (bytesRead == -1 && errno == EWOULDBLOCK)
+ return -2;
return bytesRead;
}
@@ -1126,7 +1111,7 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
if (stderrChannel.pipe[0] != -1)
add_fd(nfds, stderrChannel.pipe[0], &fdread);
- if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
+ if (!stdinChannel.buffer.isEmpty() && stdinChannel.pipe[1] != -1)
add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
@@ -1188,7 +1173,7 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
QList<QSocketNotifier *> notifiers = defaultNotifiers();
#endif
- while (!writeBuffer.isEmpty()) {
+ while (!stdinChannel.buffer.isEmpty()) {
fd_set fdread;
fd_set fdwrite;
@@ -1207,7 +1192,7 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
add_fd(nfds, stderrChannel.pipe[0], &fdread);
- if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
+ if (!stdinChannel.buffer.isEmpty() && stdinChannel.pipe[1] != -1)
add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
@@ -1282,7 +1267,7 @@ bool QProcessPrivate::waitForFinished(int msecs)
if (processState == QProcess::Running)
add_fd(nfds, deathPipe[0], &fdread);
- if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
+ if (!stdinChannel.buffer.isEmpty() && stdinChannel.pipe[1] != -1)
add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index d7050034bd..7b3f1f8f58 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -158,7 +158,7 @@ static void duplicateStdWriteChannel(Q_PIPE *pipe, DWORD nStdHandle)
This function must be called in order: stdin, stdout, stderr
*/
-bool QProcessPrivate::createChannel(Channel &channel)
+bool QProcessPrivate::openChannel(Channel &channel)
{
Q_Q(QProcess);
@@ -180,34 +180,31 @@ bool QProcessPrivate::createChannel(Channel &channel)
&channel.pipe[0], 0, TRUE, DUPLICATE_SAME_ACCESS);
}
} else {
- QWindowsPipeReader *pipeReader = 0;
if (&channel == &stdoutChannel) {
if (processChannelMode != QProcess::ForwardedChannels
&& processChannelMode != QProcess::ForwardedOutputChannel) {
- if (!stdoutReader) {
- stdoutReader = new QWindowsPipeReader(q);
- q->connect(stdoutReader, SIGNAL(readyRead()), SLOT(_q_canReadStandardOutput()));
+ if (!stdoutChannel.reader) {
+ stdoutChannel.reader = new QWindowsPipeReader(q);
+ q->connect(stdoutChannel.reader, SIGNAL(readyRead()), SLOT(_q_canReadStandardOutput()));
}
- pipeReader = stdoutReader;
} else {
duplicateStdWriteChannel(channel.pipe, STD_OUTPUT_HANDLE);
}
} else /* if (&channel == &stderrChannel) */ {
if (processChannelMode != QProcess::ForwardedChannels
&& processChannelMode != QProcess::ForwardedErrorChannel) {
- if (!stderrReader) {
- stderrReader = new QWindowsPipeReader(q);
- q->connect(stderrReader, SIGNAL(readyRead()), SLOT(_q_canReadStandardError()));
+ if (!stderrChannel.reader) {
+ stderrChannel.reader = new QWindowsPipeReader(q);
+ q->connect(stderrChannel.reader, SIGNAL(readyRead()), SLOT(_q_canReadStandardError()));
}
- pipeReader = stderrReader;
} else {
duplicateStdWriteChannel(channel.pipe, STD_ERROR_HANDLE);
}
}
- if (pipeReader) {
+ if (channel.reader) {
qt_create_pipe(channel.pipe, false);
- pipeReader->setHandle(channel.pipe[0]);
- pipeReader->startAsyncRead();
+ channel.reader->setHandle(channel.pipe[0]);
+ channel.reader->startAsyncRead();
}
}
@@ -332,25 +329,15 @@ void QProcessPrivate::destroyPipe(Q_PIPE pipe[2])
}
}
-void QProcessPrivate::destroyChannel(Channel *channel)
+void QProcessPrivate::closeChannel(Channel *channel)
{
if (channel == &stdinChannel) {
- if (pipeWriter) {
- delete pipeWriter;
- pipeWriter = 0;
- }
- } else if (channel == &stdoutChannel) {
- if (stdoutReader) {
- stdoutReader->stop();
- stdoutReader->deleteLater();
- stdoutReader = 0;
- }
- } else if (channel == &stderrChannel) {
- if (stderrReader) {
- stderrReader->stop();
- stderrReader->deleteLater();
- stderrReader = 0;
- }
+ delete stdinChannel.writer;
+ stdinChannel.writer = 0;
+ } else if (channel->reader) {
+ channel->reader->stop();
+ channel->reader->deleteLater();
+ channel->reader = 0;
}
destroyPipe(channel->pipe);
}
@@ -486,9 +473,9 @@ void QProcessPrivate::startProcess()
q->setProcessState(QProcess::Starting);
- if (!createChannel(stdinChannel) ||
- !createChannel(stdoutChannel) ||
- !createChannel(stderrChannel))
+ if (!openChannel(stdinChannel) ||
+ !openChannel(stdoutChannel) ||
+ !openChannel(stderrChannel))
return;
QString args = qt_create_commandline(program, arguments);
@@ -577,47 +564,25 @@ bool QProcessPrivate::processStarted()
return processState == QProcess::Running;
}
-qint64 QProcessPrivate::bytesAvailableFromStdout() const
+qint64 QProcessPrivate::bytesAvailableInChannel(const Channel *channel) const
{
- if (stdoutChannel.pipe[0] == INVALID_Q_PIPE)
- return 0;
+ Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE);
+ Q_ASSERT(channel->reader);
- if (!stdoutReader)
- return 0;
-
- DWORD bytesAvail = stdoutReader->bytesAvailable();
+ DWORD bytesAvail = channel->reader->bytesAvailable();
#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::bytesAvailableFromStdout() == %d", bytesAvail);
+ qDebug("QProcessPrivate::bytesAvailableInChannel(%d) == %d", channel - &stdinChannel, bytesAvail);
#endif
return bytesAvail;
}
-qint64 QProcessPrivate::bytesAvailableFromStderr() const
+qint64 QProcessPrivate::readFromChannel(const Channel *channel, char *data, qint64 maxlen)
{
- if (stderrChannel.pipe[0] == INVALID_Q_PIPE)
- return 0;
-
- if (!stderrReader)
- return 0;
-
- DWORD bytesAvail = stderrReader->bytesAvailable();
-#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::bytesAvailableFromStderr() == %d", bytesAvail);
-#endif
- return bytesAvail;
+ Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE);
+ Q_ASSERT(channel->reader);
+ return channel->reader->read(data, maxlen);
}
-qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen)
-{
- return stdoutReader ? stdoutReader->read(data, maxlen) : 0;
-}
-
-qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen)
-{
- return stderrReader ? stderrReader->read(data, maxlen) : 0;
-}
-
-
static BOOL QT_WIN_CALLBACK qt_terminateApp(HWND hwnd, LPARAM procId)
{
DWORD currentProcId = 0;
@@ -659,20 +624,20 @@ bool QProcessPrivate::waitForStarted(int)
bool QProcessPrivate::drainOutputPipes()
{
- if (!stdoutReader && !stderrReader)
+ if (!stdoutChannel.reader && !stderrChannel.reader)
return false;
bool someReadyReadEmitted = false;
forever {
bool readyReadEmitted = false;
bool readOperationActive = false;
- if (stdoutReader) {
- readyReadEmitted |= stdoutReader->waitForReadyRead(0);
- readOperationActive = stdoutReader && stdoutReader->isReadOperationActive();
+ if (stdoutChannel.reader) {
+ readyReadEmitted |= stdoutChannel.reader->waitForReadyRead(0);
+ readOperationActive = stdoutChannel.reader && stdoutChannel.reader->isReadOperationActive();
}
- if (stderrReader) {
- readyReadEmitted |= stderrReader->waitForReadyRead(0);
- readOperationActive |= stderrReader && stderrReader->isReadOperationActive();
+ if (stderrChannel.reader) {
+ readyReadEmitted |= stderrChannel.reader->waitForReadyRead(0);
+ readOperationActive |= stderrChannel.reader && stderrChannel.reader->isReadOperationActive();
}
someReadyReadEmitted |= readyReadEmitted;
if (!readOperationActive || !readyReadEmitted)
@@ -690,13 +655,13 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
QIncrementalSleepTimer timer(msecs);
forever {
- if (!writeBuffer.isEmpty() && !_q_canWrite())
+ if (!stdinChannel.buffer.isEmpty() && !_q_canWrite())
return false;
- if (pipeWriter && pipeWriter->waitForWrite(0))
+ if (stdinChannel.writer && stdinChannel.writer->waitForWrite(0))
timer.resetIncrements();
- if ((stdoutReader && stdoutReader->waitForReadyRead(0))
- || (stderrReader && stderrReader->waitForReadyRead(0)))
+ if ((stdoutChannel.reader && stdoutChannel.reader->waitForReadyRead(0))
+ || (stderrChannel.reader && stderrChannel.reader->waitForReadyRead(0)))
return true;
if (!pid)
@@ -726,12 +691,12 @@ bool QProcessPrivate::waitForBytesWritten(int 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());
+ // last time we called stdinChannel.writer->waitForWrite().
+ bool pendingDataInPipe = stdinChannel.writer && (stdinChannel.writer->bytesToWrite() || stdinChannel.writer->hadWritten());
// If we don't have pending data, and our write buffer is
// empty, we fail.
- if (!pendingDataInPipe && writeBuffer.isEmpty())
+ if (!pendingDataInPipe && stdinChannel.buffer.isEmpty())
return false;
// If we don't have pending data and we do have data in our
@@ -746,21 +711,21 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
// 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()
+ // and the stdinChannel.writer is now dead, that means _q_canWrite()
// destroyed the writer after it successfully wrote the last
// batch.
- if (!pipeWriter || pipeWriter->waitForWrite(0))
+ if (!stdinChannel.writer || stdinChannel.writer->waitForWrite(0))
return true;
// If we wouldn't write anything, check if we can read stdout.
- if (bytesAvailableFromStdout() != 0) {
- _q_canReadStandardOutput();
+ if (bytesAvailableInChannel(&stdoutChannel) != 0) {
+ tryReadFromChannel(&stdoutChannel);
timer.resetIncrements();
}
// Check if we can read stderr.
- if (bytesAvailableFromStderr() != 0) {
- _q_canReadStandardError();
+ if (bytesAvailableInChannel(&stderrChannel) != 0) {
+ tryReadFromChannel(&stderrChannel);
timer.resetIncrements();
}
@@ -795,13 +760,13 @@ bool QProcessPrivate::waitForFinished(int msecs)
QIncrementalSleepTimer timer(msecs);
forever {
- if (!writeBuffer.isEmpty() && !_q_canWrite())
+ if (!stdinChannel.buffer.isEmpty() && !_q_canWrite())
return false;
- if (pipeWriter && pipeWriter->waitForWrite(0))
+ if (stdinChannel.writer && stdinChannel.writer->waitForWrite(0))
timer.resetIncrements();
- if (stdoutReader && stdoutReader->waitForReadyRead(0))
+ if (stdoutChannel.reader && stdoutChannel.reader->waitForReadyRead(0))
timer.resetIncrements();
- if (stderrReader && stderrReader->waitForReadyRead(0))
+ if (stderrChannel.reader && stderrChannel.reader->waitForReadyRead(0))
timer.resetIncrements();
if (!pid) {
@@ -837,33 +802,32 @@ void QProcessPrivate::findExitCode()
void QProcessPrivate::flushPipeWriter()
{
- if (pipeWriter && pipeWriter->bytesToWrite() > 0) {
- pipeWriter->waitForWrite(ULONG_MAX);
- }
+ if (stdinChannel.writer && stdinChannel.writer->bytesToWrite() > 0)
+ stdinChannel.writer->waitForWrite(ULONG_MAX);
}
qint64 QProcessPrivate::pipeWriterBytesToWrite() const
{
- return pipeWriter ? pipeWriter->bytesToWrite() : qint64(0);
+ return stdinChannel.writer ? stdinChannel.writer->bytesToWrite() : qint64(0);
}
qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
{
Q_Q(QProcess);
- if (!pipeWriter) {
- pipeWriter = new QWindowsPipeWriter(stdinChannel.pipe[1], q);
- pipeWriter->start();
+ if (!stdinChannel.writer) {
+ stdinChannel.writer = new QWindowsPipeWriter(stdinChannel.pipe[1], q);
+ stdinChannel.writer->start();
}
- return pipeWriter->write(data, maxlen);
+ return stdinChannel.writer->write(data, maxlen);
}
bool QProcessPrivate::waitForWrite(int msecs)
{
Q_Q(QProcess);
- if (!pipeWriter || pipeWriter->waitForWrite(msecs))
+ if (!stdinChannel.writer || stdinChannel.writer->waitForWrite(msecs))
return true;
processError = QProcess::Timedout;
@@ -875,7 +839,7 @@ void QProcessPrivate::_q_notified()
{
notifier->stop();
- if (!writeBuffer.isEmpty() && (!pipeWriter || pipeWriter->waitForWrite(0)))
+ if (!stdinChannel.buffer.isEmpty() && (!stdinChannel.writer || stdinChannel.writer->waitForWrite(0)))
_q_canWrite();
if (processState != QProcess::NotRunning)
diff --git a/src/corelib/io/qprocess_wince.cpp b/src/corelib/io/qprocess_wince.cpp
index ad9a328133..e0bee48598 100644
--- a/src/corelib/io/qprocess_wince.cpp
+++ b/src/corelib/io/qprocess_wince.cpp
@@ -62,7 +62,7 @@ void QProcessPrivate::destroyPipe(Q_PIPE pipe[2])
Q_UNUSED(pipe);
}
-void QProcessPrivate::destroyChannel(Channel *channel)
+void QProcessPrivate::closeChannel(Channel *channel)
{
Q_UNUSED(channel);
}
@@ -174,22 +174,12 @@ bool QProcessPrivate::processStarted()
return processState == QProcess::Running;
}
-qint64 QProcessPrivate::bytesAvailableFromStdout() const
+qint64 QProcessPrivate::bytesAvailableInChannel(const Channel *) const
{
return 0;
}
-qint64 QProcessPrivate::bytesAvailableFromStderr() const
-{
- return 0;
-}
-
-qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen)
-{
- return -1;
-}
-
-qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen)
+qint64 QProcessPrivate::readFromChannel(const Channel *, char *data, qint64 maxlen)
{
return -1;
}
diff --git a/src/corelib/io/qstandardpaths_winrt.cpp b/src/corelib/io/qstandardpaths_winrt.cpp
index aa3b710f52..81b9d10baf 100644
--- a/src/corelib/io/qstandardpaths_winrt.cpp
+++ b/src/corelib/io/qstandardpaths_winrt.cpp
@@ -104,14 +104,23 @@ QString QStandardPaths::writableLocation(StandardLocation type)
case GenericCacheLocation:
return writableLocation(GenericDataLocation) + QLatin1String("/cache");
- case RuntimeLocation:
- case HomeLocation:
- result = QDir::homePath();
- break;
-
case TempLocation:
result = QDir::tempPath();
break;
+
+ case ApplicationsLocation:
+ case DesktopLocation:
+ case FontsLocation:
+ case HomeLocation:
+ case RuntimeLocation:
+ // these are read-only
+ break;
+
+ case DocumentsLocation:
+ case MusicLocation:
+ case MoviesLocation:
+ case PicturesLocation:
+ case DownloadLocation:
default:
Q_UNIMPLEMENTED();
}
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp
index 7dd2125e70..d8a3ec9b42 100644
--- a/src/corelib/io/qwindowspipereader.cpp
+++ b/src/corelib/io/qwindowspipereader.cpp
@@ -132,7 +132,7 @@ qint64 QWindowsPipeReader::bytesAvailable() const
qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
{
if (pipeBroken && actualReadBufferSize == 0)
- return -1; // signal EOF
+ return 0; // signal EOF
qint64 readSoFar;
// If startAsyncRead() has read data, copy it to its destination.
@@ -159,6 +159,8 @@ qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
emitReadyReadTimer->stop();
if (!readSequenceStarted)
startAsyncRead();
+ if (readSoFar == 0)
+ return -2; // signal EWOULDBLOCK
}
return readSoFar;