diff options
author | Sergio Ahumada <sergio.ahumada@digia.com> | 2013-09-21 17:34:59 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-21 18:39:13 +0200 |
commit | 4cebef621bb108c76f3cc8bfd0fdf77174b6499d (patch) | |
tree | 657eceb4539343312e7cd33b3644d1b1ec116ae2 /src/corelib/io | |
parent | 8969f57b6abef31d2e27500742dffa5498e38a46 (diff) | |
parent | a5d34b34fbd867bd13ce94cdaf55d96576d4d14d (diff) |
Merge "Merge branch 'stable' into dev" into refs/staging/dev
Diffstat (limited to 'src/corelib/io')
-rw-r--r-- | src/corelib/io/qfilesystemwatcher_inotify.cpp | 21 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemwatcher_inotify_p.h | 5 | ||||
-rw-r--r-- | src/corelib/io/qprocess_unix.cpp | 40 |
3 files changed, 52 insertions, 14 deletions
diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp index 024af79c33..c731f3d417 100644 --- a/src/corelib/io/qfilesystemwatcher_inotify.cpp +++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp @@ -365,11 +365,11 @@ void QInotifyFileSystemWatcherEngine::readFromInotify() // qDebug() << "inotify event, wd" << event.wd << "mask" << hex << event.mask; int id = event.wd; - QString path = idToPath.value(id); + QString path = getPathFromID(id); if (path.isEmpty()) { // perhaps a directory? id = -id; - path = idToPath.value(id); + path = getPathFromID(id); if (path.isEmpty()) continue; } @@ -378,8 +378,9 @@ void QInotifyFileSystemWatcherEngine::readFromInotify() if ((event.mask & (IN_DELETE_SELF | IN_MOVE_SELF | IN_UNMOUNT)) != 0) { pathToID.remove(path); - idToPath.remove(id); - inotify_rm_watch(inotifyFd, event.wd); + idToPath.remove(id, getPathFromID(id)); + if (!idToPath.contains(id)) + inotify_rm_watch(inotifyFd, event.wd); if (id < 0) emit directoryChanged(path, true); @@ -394,6 +395,18 @@ void QInotifyFileSystemWatcherEngine::readFromInotify() } } +QString QInotifyFileSystemWatcherEngine::getPathFromID(int id) const +{ + QHash<int, QString>::const_iterator i = idToPath.find(id); + while (i != idToPath.constEnd() && i.key() == id) { + if ((i + 1) == idToPath.constEnd() || (i + 1).key() != id) { + return i.value(); + } + ++i; + } + return QString(); +} + QT_END_NAMESPACE #endif // QT_NO_FILESYSTEMWATCHER diff --git a/src/corelib/io/qfilesystemwatcher_inotify_p.h b/src/corelib/io/qfilesystemwatcher_inotify_p.h index 959d9edc12..d02f04eed6 100644 --- a/src/corelib/io/qfilesystemwatcher_inotify_p.h +++ b/src/corelib/io/qfilesystemwatcher_inotify_p.h @@ -79,10 +79,13 @@ private Q_SLOTS: void readFromInotify(); private: + QString getPathFromID(int id) const; + +private: QInotifyFileSystemWatcherEngine(int fd, QObject *parent); int inotifyFd; QHash<QString, int> pathToID; - QHash<int, QString> idToPath; + QMultiHash<int, QString> idToPath; QSocketNotifier notifier; }; diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 9868ea624a..eab3890beb 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -121,17 +121,33 @@ static const int errorBufferMax = 512; static int qt_qprocess_deadChild_pipe[2]; static struct sigaction qt_sa_old_sigchld_handler; -static void qt_sa_sigchld_handler(int signum) +static void qt_sa_sigchld_sigaction(int signum, siginfo_t *info, void *context) { + // *Never* use the info or contect variables in this function + // (except for passing them to the next signal in the chain). + // We cannot be sure if another library or if the application + // installed a signal handler for SIGCHLD without SA_SIGINFO + // and fails to pass the arguments to us. If they do that, + // these arguments contain garbage and we'd most likely crash. + qt_safe_write(qt_qprocess_deadChild_pipe[1], "", 1); #if defined (QPROCESS_DEBUG) fprintf(stderr, "*** SIGCHLD\n"); #endif - // load it as volatile - void (*oldAction)(int) = ((volatile struct sigaction *)&qt_sa_old_sigchld_handler)->sa_handler; - if (oldAction && oldAction != SIG_IGN) - oldAction(signum); + // load as volatile + volatile struct sigaction *vsa = &qt_sa_old_sigchld_handler; + + if (qt_sa_old_sigchld_handler.sa_flags & SA_SIGINFO) { + void (*oldAction)(int, siginfo_t *, void *) = vsa->sa_sigaction; + + oldAction(signum, info, context); + } else { + void (*oldAction)(int) = vsa->sa_handler; + + if (oldAction && oldAction != SIG_IGN) + oldAction(signum); + } } static inline void add_fd(int &nfds, int fd, fd_set *fdset) @@ -197,10 +213,16 @@ QProcessManager::QProcessManager() // set up the SIGCHLD handler, which writes a single byte to the dead // child pipe every time a child dies. + struct sigaction action; - memset(&action, 0, sizeof(action)); - action.sa_handler = qt_sa_sigchld_handler; - action.sa_flags = SA_NOCLDSTOP; + // use the old handler as template, i.e., preserve the signal mask + // otherwise the original signal handler might be interrupted although it + // was marked to never be interrupted + ::sigaction(SIGCHLD, NULL, &action); + action.sa_sigaction = qt_sa_sigchld_sigaction; + // set the SA_SIGINFO flag such that we can use the three argument handler + // function + action.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; ::sigaction(SIGCHLD, &action, &qt_sa_old_sigchld_handler); processManagerInstance = this; @@ -225,7 +247,7 @@ QProcessManager::~QProcessManager() struct sigaction currentAction; ::sigaction(SIGCHLD, 0, ¤tAction); - if (currentAction.sa_handler == qt_sa_sigchld_handler) { + if (currentAction.sa_sigaction == qt_sa_sigchld_sigaction) { ::sigaction(SIGCHLD, &qt_sa_old_sigchld_handler, 0); } |