diff options
author | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-07-01 10:03:53 +0200 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-07-01 16:25:19 +0200 |
commit | a09a8d509a69ed16d8afbe15296b8332cacd6c66 (patch) | |
tree | 28645b437fd0390d903f753a44ba79626eecb8ac /src/corelib/io | |
parent | 4b28152da64f7f23a1bbb810d8cdb7626a5f0b8e (diff) | |
parent | 83f06da1c6bffff61af78cbe75a0691d53742b53 (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.cpp | 7 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemwatcher_fsevents.mm | 28 | ||||
-rw-r--r-- | src/corelib/io/qloggingcategory.cpp | 40 | ||||
-rw-r--r-- | src/corelib/io/qloggingcategory.h | 35 | ||||
-rw-r--r-- | src/corelib/io/qprocess.cpp | 164 | ||||
-rw-r--r-- | src/corelib/io/qprocess_p.h | 28 | ||||
-rw-r--r-- | src/corelib/io/qprocess_unix.cpp | 59 | ||||
-rw-r--r-- | src/corelib/io/qprocess_win.cpp | 160 | ||||
-rw-r--r-- | src/corelib/io/qprocess_wince.cpp | 16 | ||||
-rw-r--r-- | src/corelib/io/qstandardpaths_winrt.cpp | 19 | ||||
-rw-r--r-- | src/corelib/io/qwindowspipereader.cpp | 4 |
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; |