summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
authorSergio Ahumada <sergio.ahumada@digia.com>2013-09-21 17:34:59 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-21 18:39:13 +0200
commit4cebef621bb108c76f3cc8bfd0fdf77174b6499d (patch)
tree657eceb4539343312e7cd33b3644d1b1ec116ae2 /src/corelib/io
parent8969f57b6abef31d2e27500742dffa5498e38a46 (diff)
parenta5d34b34fbd867bd13ce94cdaf55d96576d4d14d (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.cpp21
-rw-r--r--src/corelib/io/qfilesystemwatcher_inotify_p.h5
-rw-r--r--src/corelib/io/qprocess_unix.cpp40
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, &currentAction);
- if (currentAction.sa_handler == qt_sa_sigchld_handler) {
+ if (currentAction.sa_sigaction == qt_sa_sigchld_sigaction) {
::sigaction(SIGCHLD, &qt_sa_old_sigchld_handler, 0);
}