diff options
author | Arno <am@disconnect.de> | 2013-08-28 09:32:30 +0200 |
---|---|---|
committer | Arno <am@disconnect.de> | 2013-08-28 09:32:30 +0200 |
commit | 1ee897fbb51cb431cba7690076a29a3ca2ddc1a7 (patch) | |
tree | 127c2ff9ff239e672159d44aa161e99ec222898c | |
parent | dbfc4f7bf395bf20aa21058372d47d17d040f553 (diff) | |
download | SheMov-1ee897fbb51cb431cba7690076a29a3ca2ddc1a7.tar.gz SheMov-1ee897fbb51cb431cba7690076a29a3ca2ddc1a7.tar.bz2 SheMov-1ee897fbb51cb431cba7690076a29a3ca2ddc1a7.zip |
Fix crashes in SmDirWatcher (again)
This reverts commit dbfc4f7bf395bf20aa21058372d47d17d040f553. It was
totally and utterly wrong.
This is what really happened, hopefully:
Since a Semaphore can guard more than a single resource, it could happen
that both mSemUsed and mSemFree were available at the same time. So it
could happen that both the watcher and the datacollector tried to access
the dataqueue at the same time. Since ->dequeue() is not atomic, this
could throw of the internal iterator from the QList, resulting in a
crash.
The solution is simple: Guard it with a shared Mutex.
-rw-r--r-- | smdirwatcher.cpp | 16 | ||||
-rw-r--r-- | smdirwatcher.h | 4 |
2 files changed, 14 insertions, 6 deletions
diff --git a/smdirwatcher.cpp b/smdirwatcher.cpp index 839b021..3143212 100644 --- a/smdirwatcher.cpp +++ b/smdirwatcher.cpp @@ -32,8 +32,9 @@ SmDirWatcher::SmDirWatcher(int numFields, QObject *parent) : QThread(parent), mF mCollector = new SmDataColletor(numFields, this); mSemFree = new QSemaphore(1024); mSemUsed = new QSemaphore; + mQueueMx = new QMutex; mDataQueue = new QQueue<QPair<QString, DWEvent> >(); - mCollector->init(mSemFree, mSemUsed, mDataQueue); + mCollector->init(mSemFree, mSemUsed, mDataQueue, mQueueMx); mCollector->start(); } @@ -50,7 +51,9 @@ void SmDirWatcher::setDir(const QString &dir){ mCurrent = dir; mSemFree->acquire(); QPair<QString, DWEvent> c = qMakePair(dir, Populate); + mQueueMx->lock(); mDataQueue->enqueue(c); + mQueueMx->unlock(); mSemUsed->release(); } @@ -81,9 +84,9 @@ void SmDirWatcher::run(){ goto out; } c = qMakePair(name, curEvent); - if(!mDataQueue->contains(c)){ - mDataQueue->enqueue(c); - } + mQueueMx->lock(); + mDataQueue->enqueue(c); + mQueueMx->unlock(); out: mSemUsed->release(); i += sizeof(inotify_event) + e->len; @@ -109,10 +112,11 @@ SmDataColletor::SmDataColletor(const int numFields, QObject *parent) : QThread(p mMovPresentQ->prepare("SELECT COUNT(cmd5sum) FROM files WHERE cmd5sum = :md5"); } -void SmDataColletor::init(QSemaphore *set, QSemaphore *get, QQueue<QPair<QString, SmDirWatcher::DWEvent> > *data){ +void SmDataColletor::init(QSemaphore *set, QSemaphore *get, QQueue<QPair<QString, SmDirWatcher::DWEvent> > *data, QMutex *queueMx){ mSemFree = set; mSemUsed = get; mDataQueue = data; + mQueueMx = queueMx; } void SmDataColletor::setCheckForPresent(bool present){ @@ -128,7 +132,9 @@ void SmDataColletor::run(){ mSemFree->release(); break; } + mQueueMx->lock(); QPair<QString, SmDirWatcher::DWEvent> cur = mDataQueue->dequeue(); + mQueueMx->unlock(); if(cur.second == SmDirWatcher::Populate){ SmTreeItem *i = populate(cur.first); SmTreeItem *copy = new SmTreeItem(*i); diff --git a/smdirwatcher.h b/smdirwatcher.h index 77d0d97..fda828b 100644 --- a/smdirwatcher.h +++ b/smdirwatcher.h @@ -45,6 +45,7 @@ class SmDirWatcher : public QThread { QSemaphore *mSemFree; QSemaphore *mSemUsed; QQueue<QPair<QString, DWEvent> > *mDataQueue; + QMutex *mQueueMx; char *mINdata; int mBufLen; }; @@ -53,7 +54,7 @@ class SmDataColletor : public QThread { Q_OBJECT public: explicit SmDataColletor(const int numFields, QObject *parent = 0); - void init(QSemaphore *set, QSemaphore *get, QQueue<QPair<QString, SmDirWatcher::DWEvent> > *data); + void init(QSemaphore *set, QSemaphore *get, QQueue<QPair<QString, SmDirWatcher::DWEvent> > *data, QMutex *queueMx); public slots: void setCheckForPresent(bool present); @@ -71,6 +72,7 @@ class SmDataColletor : public QThread { QString mCurrent; QSemaphore *mSemFree; QSemaphore *mSemUsed; + QMutex *mQueueMx; QQueue<QPair<QString, SmDirWatcher::DWEvent> > *mDataQueue; int mMode; const int mNumFields; |