diff options
author | Olivier Goffart <olivier.goffart@nokia.com> | 2011-06-24 09:12:15 (GMT) |
---|---|---|
committer | Olivier Goffart <olivier.goffart@nokia.com> | 2011-06-24 09:12:15 (GMT) |
commit | 11cc0f661911628fb51c92d30c684eb1cea01145 (patch) | |
tree | 3f89e82669b12ea49e0586d3ff14c0d01594301e /src/corelib/io | |
parent | 9d5b0e31f287ce502eaf9a2c0876d900424c80ab (diff) | |
parent | 164728f711136356a6c3482f762321b01c9d82dd (diff) | |
download | Qt-11cc0f661911628fb51c92d30c684eb1cea01145.zip Qt-11cc0f661911628fb51c92d30c684eb1cea01145.tar.gz Qt-11cc0f661911628fb51c92d30c684eb1cea01145.tar.bz2 |
Merge remote-tracking branch 'origin/4.8'
Diffstat (limited to 'src/corelib/io')
-rw-r--r-- | src/corelib/io/qdatastream.cpp | 3 | ||||
-rw-r--r-- | src/corelib/io/qfile.cpp | 2 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemengine.cpp | 2 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemengine_unix.cpp | 11 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemwatcher_fsevents.cpp | 24 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemwatcher_fsevents_p.h | 4 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemwatcher_symbian.cpp | 4 | ||||
-rw-r--r-- | src/corelib/io/qfsfileengine.cpp | 2 | ||||
-rw-r--r-- | src/corelib/io/qprocess.cpp | 10 | ||||
-rw-r--r-- | src/corelib/io/qprocess_p.h | 8 | ||||
-rw-r--r-- | src/corelib/io/qprocess_unix.cpp | 183 | ||||
-rw-r--r-- | src/corelib/io/qurl.cpp | 2 |
12 files changed, 211 insertions, 44 deletions
diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index 8c27430..b397c1a 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -584,8 +584,9 @@ void QDataStream::setByteOrder(ByteOrder bo) \value Qt_4_3 Version 9 (Qt 4.3) \value Qt_4_4 Version 10 (Qt 4.4) \value Qt_4_5 Version 11 (Qt 4.5) - \value Qt_4_6 Version 12 (Qt 4.6) + \value Qt_4_6 Version 12 (Qt 4.6, Qt 4.7, Qt 4.8) \value Qt_4_7 Same as Qt_4_6. + \value Qt_4_8 Same as Qt_4_6. \sa setVersion(), version() */ diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 9d6641c..66edf58 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -1656,6 +1656,8 @@ bool QFile::atEnd() const } /*! + \fn bool QFile::seek(qint64 pos) + For random-access devices, this function sets the current position to \a pos, returning true on success, or false if an error occurred. For sequential devices, the default behavior is to do nothing and diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp index 9590e39..97669ac 100644 --- a/src/corelib/io/qfilesystemengine.cpp +++ b/src/corelib/io/qfilesystemengine.cpp @@ -196,7 +196,7 @@ static bool _q_resolveEntryAndCreateLegacyEngine_recursive(QFileSystemEntry &ent Resolves the \a entry (see QDir::searchPaths) and returns an engine for it, but never a QFSFileEngine. - \returns a file engine that can be used to access the entry. Returns 0 if + Returns a file engine that can be used to access the entry. Returns 0 if QFileSystemEngine API should be used to query and interact with the file system object. */ diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index f1e0758..b0ebfbd 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -180,7 +180,8 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath())); #else char *ret = 0; -# if defined(Q_OS_MAC) && !defined(QT_NO_CORESERVICES) +# if defined(Q_OS_MAC) +# if !defined(QT_NO_CORESERVICES) // Mac OS X 10.5.x doesn't support the realpath(X,0) extension we use here. if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) { ret = realpath(entry.nativeFilePath().constData(), (char*)0); @@ -197,9 +198,13 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, return QFileSystemEntry(ret); } } -# else +# else + ret = (char*)malloc(PATH_MAX); + realpath(entry.nativeFilePath().constData(), (char*)ret); +# endif //!defined(QT_NO_CORESERVICES) +# else ret = realpath(entry.nativeFilePath().constData(), (char*)0); -# endif +# endif //defined(Q_OS_MAC) if (ret) { data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute; data.entryFlags |= QFileSystemMetaData::ExistsAttribute; diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.cpp b/src/corelib/io/qfilesystemwatcher_fsevents.cpp index 6ae6e38..4ae7cf8 100644 --- a/src/corelib/io/qfilesystemwatcher_fsevents.cpp +++ b/src/corelib/io/qfilesystemwatcher_fsevents.cpp @@ -57,13 +57,15 @@ #include <sys/types.h> #include <CoreFoundation/CFRunLoop.h> #include <CoreFoundation/CFUUID.h> +#if !defined( QT_NO_CORESERVICES ) #include <CoreServices/CoreServices.h> +#endif #include <AvailabilityMacros.h> #include <private/qcore_mac_p.h> QT_BEGIN_NAMESPACE -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) // Static operator overloading so for the sake of some convieniece. // They only live in this compilation unit to avoid polluting Qt in general. static bool operator==(const struct ::timespec &left, const struct ::timespec &right) @@ -152,7 +154,7 @@ QFSEventsFileSystemWatcherEngine::QFSEventsFileSystemWatcherEngine() QFSEventsFileSystemWatcherEngine::~QFSEventsFileSystemWatcherEngine() { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) // I assume that at this point, QFileSystemWatcher has already called stop // on me, so I don't need to invalidate or stop my stream, simply // release it. @@ -171,7 +173,7 @@ QStringList QFSEventsFileSystemWatcherEngine::addPaths(const QStringList &paths, QStringList *files, QStringList *directories) { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) stop(); wait(); QMutexLocker locker(&mutex); @@ -257,7 +259,7 @@ QStringList QFSEventsFileSystemWatcherEngine::addPaths(const QStringList &paths, void QFSEventsFileSystemWatcherEngine::warmUpFSEvents() { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) // This function assumes that the mutex has already been grabbed before calling it. // It exits with the mutex still locked (Q_ASSERT(mutex.isLocked()) ;-). start(); @@ -269,7 +271,7 @@ QStringList QFSEventsFileSystemWatcherEngine::removePaths(const QStringList &pat QStringList *files, QStringList *directories) { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) stop(); wait(); QMutexLocker locker(&mutex); @@ -336,7 +338,7 @@ QStringList QFSEventsFileSystemWatcherEngine::removePaths(const QStringList &pat #endif } -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) void QFSEventsFileSystemWatcherEngine::updateList(PathInfoList &list, bool directory, bool emitSignals) { PathInfoList::iterator End = list.end(); @@ -396,7 +398,7 @@ void QFSEventsFileSystemWatcherEngine::fseventsCallback(ConstFSEventStreamRef , const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId []) { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) QFSEventsFileSystemWatcherEngine *watcher = static_cast<QFSEventsFileSystemWatcherEngine *>(clientCallBackInfo); QMutexLocker locker(&watcher->mutex); CFArrayRef paths = static_cast<CFArrayRef>(eventPaths); @@ -431,7 +433,7 @@ void QFSEventsFileSystemWatcherEngine::fseventsCallback(ConstFSEventStreamRef , void QFSEventsFileSystemWatcherEngine::stop() { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) QMutexLocker locker(&mutex); stopFSStream(fsStream); if (threadsRunLoop) { @@ -443,13 +445,13 @@ void QFSEventsFileSystemWatcherEngine::stop() void QFSEventsFileSystemWatcherEngine::updateFiles() { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) QMutexLocker locker(&mutex); updateHash(filePathInfoHash); updateHash(dirPathInfoHash); if (filePathInfoHash.isEmpty() && dirPathInfoHash.isEmpty()) { // Everything disappeared before we got to start, don't bother. -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) // Code duplicated from stop(), with the exception that we // don't wait on waitForStop here. Doing this will lead to // a deadlock since this function is called from the worker @@ -467,7 +469,7 @@ void QFSEventsFileSystemWatcherEngine::updateFiles() void QFSEventsFileSystemWatcherEngine::run() { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) threadsRunLoop = CFRunLoopGetCurrent(); FSEventStreamScheduleWithRunLoop(fsStream, threadsRunLoop, kCFRunLoopDefaultMode); bool startedOK = FSEventStreamStart(fsStream); diff --git a/src/corelib/io/qfilesystemwatcher_fsevents_p.h b/src/corelib/io/qfilesystemwatcher_fsevents_p.h index 2466a6e..515c32e 100644 --- a/src/corelib/io/qfilesystemwatcher_fsevents_p.h +++ b/src/corelib/io/qfilesystemwatcher_fsevents_p.h @@ -74,7 +74,7 @@ typedef uint64_t FSEventStreamEventId; QT_BEGIN_NAMESPACE -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined(QT_NO_CORESERVICES) // Yes, I use a stat64 element here. QFileInfo requires too much knowledge about implementation // details to be used as a long-standing record. Since I'm going to have to store this information, I can // do the stat myself too. @@ -117,7 +117,7 @@ private: QMutex mutex; QWaitCondition waitCondition; QWaitCondition waitForStop; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) PathHash filePathInfoHash; PathHash dirPathInfoHash; void updateHash(PathHash &pathHash); diff --git a/src/corelib/io/qfilesystemwatcher_symbian.cpp b/src/corelib/io/qfilesystemwatcher_symbian.cpp index 6e5e911..63cc4f1 100644 --- a/src/corelib/io/qfilesystemwatcher_symbian.cpp +++ b/src/corelib/io/qfilesystemwatcher_symbian.cpp @@ -62,9 +62,9 @@ QNotifyChangeEvent::QNotifyChangeEvent(RFs &fs, const TDesC &file, failureCount(0) { if (isDir) { - fsSession.NotifyChange(ENotifyEntry, iStatus, file); + fsSession.NotifyChange(ENotifyEntry, iStatus, watchedPath); } else { - fsSession.NotifyChange(ENotifyAll, iStatus, file); + fsSession.NotifyChange(ENotifyAll, iStatus, watchedPath); } CActiveScheduler::Add(this); SetActive(); diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 4894754..0d23a27 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -472,10 +472,10 @@ qint64 QFSFileEngine::size() const return d->nativeSize(); } +#ifndef Q_OS_WIN /*! \internal */ -#ifndef Q_OS_WIN qint64 QFSFileEnginePrivate::sizeFdFh() const { Q_Q(const QFSFileEngine); diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 70a70c2..4b689c5 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -751,12 +751,16 @@ QProcessPrivate::QProcessPrivate() sequenceNumber = 0; exitCode = 0; exitStatus = QProcess::NormalExit; +#ifndef Q_OS_QNX startupSocketNotifier = 0; +#endif deathNotifier = 0; notifier = 0; pipeWriter = 0; +#ifndef Q_OS_QNX childStartedPipe[0] = INVALID_Q_PIPE; childStartedPipe[1] = INVALID_Q_PIPE; +#endif deathPipe[0] = INVALID_Q_PIPE; deathPipe[1] = INVALID_Q_PIPE; exitCode = 0; @@ -825,11 +829,13 @@ void QProcessPrivate::cleanup() qDeleteInEventHandler(stdinChannel.notifier); stdinChannel.notifier = 0; } +#ifndef Q_OS_QNX if (startupSocketNotifier) { startupSocketNotifier->setEnabled(false); qDeleteInEventHandler(startupSocketNotifier); startupSocketNotifier = 0; } +#endif if (deathNotifier) { deathNotifier->setEnabled(false); qDeleteInEventHandler(deathNotifier); @@ -842,7 +848,9 @@ void QProcessPrivate::cleanup() destroyPipe(stdoutChannel.pipe); destroyPipe(stderrChannel.pipe); destroyPipe(stdinChannel.pipe); +#ifndef Q_OS_QNX destroyPipe(childStartedPipe); +#endif destroyPipe(deathPipe); #ifdef Q_OS_UNIX serial = 0; @@ -1077,8 +1085,10 @@ bool QProcessPrivate::_q_startupNotification() qDebug("QProcessPrivate::startupNotification()"); #endif +#ifndef Q_OS_QNX if (startupSocketNotifier) startupSocketNotifier->setEnabled(false); +#endif if (processStarted()) { q->setProcessState(QProcess::Running); emit q->started(); diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 9adb331..f24a7bc 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -288,11 +288,15 @@ public: QRingBuffer errorReadBuffer; QRingBuffer writeBuffer; +#ifndef Q_OS_QNX Q_PIPE childStartedPipe[2]; +#endif Q_PIPE deathPipe[2]; void destroyPipe(Q_PIPE pipe[2]); +#ifndef Q_OS_QNX QSocketNotifier *startupSocketNotifier; +#endif QSocketNotifier *deathNotifier; // the wonderful windows notifier @@ -301,8 +305,10 @@ public: QWinEventNotifier *processFinishedNotifier; void startProcess(); -#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) +#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) && !defined(Q_OS_QNX) void execChild(const char *workingDirectory, char **path, char **argv, char **envp); +#elif defined(Q_OS_QNX) + pid_t spawnChild(const char *workingDirectory, char **argv, char **envp); #endif bool processStarted(); void terminateProcess(); diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 07e3087..725e4c5 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -105,6 +105,10 @@ QT_END_NAMESPACE #include <errno.h> #include <stdlib.h> #include <string.h> +#ifdef Q_OS_QNX +# include <spawn.h> +#endif + QT_BEGIN_NAMESPACE @@ -521,16 +525,6 @@ static char **_q_dupEnvironment(const QProcessEnvironmentPrivate::Hash &environm return envp; } -// under QNX RTOS we have to use vfork() when multithreading -inline pid_t qt_fork() -{ -#if defined(Q_OS_QNX) - return vfork(); -#else - return fork(); -#endif -} - #ifdef Q_OS_MAC Q_GLOBAL_STATIC(QMutex, cfbundleMutex); #endif @@ -550,15 +544,18 @@ void QProcessPrivate::startProcess() !createChannel(stdoutChannel) || !createChannel(stderrChannel)) return; +#if !defined(Q_OS_QNX) qt_create_pipe(childStartedPipe); +#endif qt_create_pipe(deathPipe); if (threadData->eventDispatcher) { +#if !defined(Q_OS_QNX) startupSocketNotifier = new QSocketNotifier(childStartedPipe[0], QSocketNotifier::Read, q); QObject::connect(startupSocketNotifier, SIGNAL(activated(int)), q, SLOT(_q_startupNotification())); - +#endif deathNotifier = new QSocketNotifier(deathPipe[0], QSocketNotifier::Read, q); QObject::connect(deathNotifier, SIGNAL(activated(int)), @@ -650,7 +647,11 @@ void QProcessPrivate::startProcess() // Start the process manager, and fork off the child process. processManager()->lock(); - pid_t childPid = qt_fork(); +#if defined(Q_OS_QNX) + pid_t childPid = spawnChild(workingDirPtr, argv, envp); +#else + pid_t childPid = fork(); +#endif int lastForkErrno = errno; if (childPid != 0) { // Clean up duplicated memory. @@ -668,7 +669,7 @@ void QProcessPrivate::startProcess() if (childPid < 0) { // Cleanup, report error and return #if defined (QPROCESS_DEBUG) - qDebug("qt_fork failed: %s", qPrintable(qt_error_string(lastForkErrno))); + qDebug("fork() failed: %s", qPrintable(qt_error_string(lastForkErrno))); #endif processManager()->unlock(); q->setProcessState(QProcess::NotRunning); @@ -679,11 +680,13 @@ void QProcessPrivate::startProcess() return; } +#if !defined(Q_OS_QNX) // Start the child. if (childPid == 0) { execChild(workingDirPtr, path, argv, envp); ::_exit(-1); } +#endif // Register the child. In the mean time, we can get a SIGCHLD, so we need // to keep the lock held to avoid a race to catch the child. @@ -694,14 +697,15 @@ void QProcessPrivate::startProcess() // parent // close the ends we don't use and make all pipes non-blocking ::fcntl(deathPipe[0], F_SETFL, ::fcntl(deathPipe[0], F_GETFL) | O_NONBLOCK); +#if !defined(Q_OS_QNX) qt_safe_close(childStartedPipe[1]); childStartedPipe[1] = -1; +#endif if (stdinChannel.pipe[0] != -1) { qt_safe_close(stdinChannel.pipe[0]); stdinChannel.pipe[0] = -1; } - if (stdinChannel.pipe[1] != -1) ::fcntl(stdinChannel.pipe[1], F_SETFL, ::fcntl(stdinChannel.pipe[1], F_GETFL) | O_NONBLOCK); @@ -709,7 +713,6 @@ void QProcessPrivate::startProcess() qt_safe_close(stdoutChannel.pipe[1]); stdoutChannel.pipe[1] = -1; } - if (stdoutChannel.pipe[0] != -1) ::fcntl(stdoutChannel.pipe[0], F_SETFL, ::fcntl(stdoutChannel.pipe[0], F_GETFL) | O_NONBLOCK); @@ -721,6 +724,7 @@ void QProcessPrivate::startProcess() ::fcntl(stderrChannel.pipe[0], F_SETFL, ::fcntl(stderrChannel.pipe[0], F_GETFL) | O_NONBLOCK); } +#if !defined(Q_OS_QNX) void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv, char **envp) { ::signal(SIGPIPE, SIG_DFL); // reset the signal that we ignored @@ -728,17 +732,17 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv Q_Q(QProcess); // copy the stdin socket (without closing on exec) - qt_safe_dup2(stdinChannel.pipe[0], fileno(stdin), 0); + qt_safe_dup2(stdinChannel.pipe[0], QT_FILENO(stdin), 0); // copy the stdout and stderr if asked to if (processChannelMode != QProcess::ForwardedChannels) { - qt_safe_dup2(stdoutChannel.pipe[1], fileno(stdout), 0); + qt_safe_dup2(stdoutChannel.pipe[1], QT_FILENO(stdout), 0); // merge stdout and stderr if asked to if (processChannelMode == QProcess::MergedChannels) { - qt_safe_dup2(fileno(stdout), fileno(stderr), 0); + qt_safe_dup2(QT_FILENO(stdout), QT_FILENO(stderr), 0); } else { - qt_safe_dup2(stderrChannel.pipe[1], fileno(stderr), 0); + qt_safe_dup2(stderrChannel.pipe[1], QT_FILENO(stderr), 0); } } @@ -807,6 +811,87 @@ bool QProcessPrivate::processStarted() return i <= 0; } +#else // Q_OS_QNX + +static pid_t doSpawn(int fd_count, int fd_map[], char **argv, char **envp, bool spawn_detached) +{ + // A multi threaded QNX Process can't fork so we call spawn() instead. + + struct inheritance inherit; + memset(&inherit, 0, sizeof(inherit)); + inherit.flags |= SPAWN_SETSID; + inherit.flags |= SPAWN_CHECK_SCRIPT; + if (spawn_detached) + inherit.flags |= SPAWN_NOZOMBIE; + inherit.flags |= SPAWN_SETSIGDEF; + sigaddset(&inherit.sigdefault, SIGPIPE); // reset the signal that we ignored + + pid_t childPid; + EINTR_LOOP(childPid, ::spawn(argv[0], fd_count, fd_map, &inherit, argv, envp)); + if (childPid == -1) { + inherit.flags |= SPAWN_SEARCH_PATH; + EINTR_LOOP(childPid, ::spawn(argv[0], fd_count, fd_map, &inherit, argv, envp)); + } + + return childPid; +} + +pid_t QProcessPrivate::spawnChild(const char *workingDir, char **argv, char **envp) +{ + Q_Q(QProcess); + + const int fd_count = 3; + int fd_map[fd_count]; + switch (processChannelMode) { + case QProcess::ForwardedChannels: + fd_map[0] = stdinChannel.pipe[0]; + fd_map[1] = QT_FILENO(stdout); + fd_map[2] = QT_FILENO(stderr); + break; + case QProcess::MergedChannels: + fd_map[0] = stdinChannel.pipe[0]; + fd_map[1] = stdoutChannel.pipe[1]; + fd_map[2] = stdoutChannel.pipe[1]; + break; + case QProcess::SeparateChannels: + fd_map[0] = stdinChannel.pipe[0]; + fd_map[1] = stdoutChannel.pipe[1]; + fd_map[2] = stderrChannel.pipe[1]; + break; + } + + // enter the working directory + char *oldWorkingDir = 0; + char buff[PATH_MAX + 1]; + if (workingDir) { + oldWorkingDir = QT_GETCWD(buff, PATH_MAX + 1); + QT_CHDIR(workingDir); + } + + pid_t childPid = doSpawn(fd_count, fd_map, argv, envp, false); + + if (oldWorkingDir) + QT_CHDIR(oldWorkingDir); + + if (childPid != -1) { + q->setProcessState(QProcess::Running); + QMetaObject::invokeMethod(q, "_q_startupNotification", Qt::QueuedConnection); + } + + return childPid; +} + +bool QProcessPrivate::processStarted() +{ + return processState == QProcess::Running; +} + +bool QProcessPrivate::waitForStarted(int /*msecs*/) +{ + return processStarted(); +} +#endif // Q_OS_QNX + qint64 QProcessPrivate::bytesAvailableFromStdout() const { int nbytes = 0; @@ -924,6 +1009,7 @@ static int qt_timeout_value(int msecs, int elapsed) return timeout < 0 ? 0 : timeout; } +#if !defined(Q_OS_QNX) bool QProcessPrivate::waitForStarted(int msecs) { Q_Q(QProcess); @@ -951,6 +1037,7 @@ bool QProcessPrivate::waitForStarted(int msecs) #endif return startedEmitted; } +#endif // Q_OS_QNX bool QProcessPrivate::waitForReadyRead(int msecs) { @@ -972,8 +1059,10 @@ bool QProcessPrivate::waitForReadyRead(int msecs) int nfds = deathPipe[0]; FD_SET(deathPipe[0], &fdread); +#if !defined(Q_OS_QNX) if (processState == QProcess::Starting) add_fd(nfds, childStartedPipe[0], &fdread); +#endif if (stdoutChannel.pipe[0] != -1) add_fd(nfds, stdoutChannel.pipe[0], &fdread); @@ -994,10 +1083,12 @@ bool QProcessPrivate::waitForReadyRead(int msecs) return false; } +#if !defined(Q_OS_QNX) if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { if (!_q_startupNotification()) return false; } +#endif bool readyReadEmitted = false; if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) { @@ -1044,8 +1135,10 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) int nfds = deathPipe[0]; FD_SET(deathPipe[0], &fdread); +#if !defined(Q_OS_QNX) if (processState == QProcess::Starting) add_fd(nfds, childStartedPipe[0], &fdread); +#endif if (stdoutChannel.pipe[0] != -1) add_fd(nfds, stdoutChannel.pipe[0], &fdread); @@ -1068,10 +1161,12 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) return false; } +#if !defined(Q_OS_QNX) if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { if (!_q_startupNotification()) return false; } +#endif if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite)) return _q_canWrite(); @@ -1109,8 +1204,10 @@ bool QProcessPrivate::waitForFinished(int msecs) FD_ZERO(&fdread); FD_ZERO(&fdwrite); +#if !defined(Q_OS_QNX) if (processState == QProcess::Starting) add_fd(nfds, childStartedPipe[0], &fdread); +#endif if (stdoutChannel.pipe[0] != -1) add_fd(nfds, stdoutChannel.pipe[0], &fdread); @@ -1134,10 +1231,12 @@ bool QProcessPrivate::waitForFinished(int msecs) return false; } +#if !defined(Q_OS_QNX) if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { if (!_q_startupNotification()) return false; } +#endif if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite)) _q_canWrite(); @@ -1199,6 +1298,47 @@ void QProcessPrivate::_q_notified() { } +#if defined(Q_OS_QNX) +bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid) +{ + QByteArray encodedWorkingDirectory = QFile::encodeName(workingDirectory); + + // enter the working directory + char *oldWorkingDir = 0; + char buff[PATH_MAX + 1]; + if (!encodedWorkingDirectory.isEmpty()) { + oldWorkingDir = QT_GETCWD(buff, PATH_MAX + 1); + QT_CHDIR(encodedWorkingDirectory.constData()); + } + + const int fd_count = 3; + int fd_map[fd_count] = { QT_FILENO(stdin), QT_FILENO(stdout), QT_FILENO(stderr) }; + + QList<QByteArray> enc_args; + enc_args.append(QFile::encodeName(program)); + for (int i = 0; i < arguments.size(); ++i) + enc_args.append(arguments.at(i).toLocal8Bit()); + + const int argc = enc_args.size(); + QScopedArrayPointer<char*> raw_argv(new char*[argc + 1]); + for (int i = 0; i < argc; ++i) + raw_argv[i] = const_cast<char *>(enc_args.at(i).data()); + raw_argv[argc] = 0; + + char **envp = 0; // inherit environment + + pid_t childPid = doSpawn(fd_count, fd_map, raw_argv.data(), envp, true); + if (pid && childPid != -1) + *pid = childPid; + + if (oldWorkingDir) + QT_CHDIR(oldWorkingDir); + + return childPid != -1; +} + +#else + bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid) { processManager()->start(); @@ -1212,7 +1352,7 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a int pidPipe[2]; qt_safe_pipe(pidPipe); - pid_t childPid = qt_fork(); + pid_t childPid = fork(); if (childPid == 0) { struct sigaction noaction; memset(&noaction, 0, sizeof(noaction)); @@ -1224,7 +1364,7 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a qt_safe_close(startedPipe[0]); qt_safe_close(pidPipe[0]); - pid_t doubleForkPid = qt_fork(); + pid_t doubleForkPid = fork(); if (doubleForkPid == 0) { qt_safe_close(pidPipe[1]); @@ -1312,6 +1452,7 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a qt_safe_close(pidPipe[0]); return success; } +#endif // Q_OS_QNX void QProcessPrivate::initializeProcessManager() { diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 83b49ce..8813656 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -6105,7 +6105,7 @@ bool QUrl::isDetached() const "//servername/path/to/file.txt". Note that only certain platforms can actually open this file using QFile::open(). - \sa toLocalFile(), isLocalFile(), QDir::toNativeSeparators + \sa toLocalFile(), isLocalFile(), QDir::toNativeSeparators() */ QUrl QUrl::fromLocalFile(const QString &localFile) { |