Fix race in QFseventsFileSystemWatcher destructor

The race goes like this:
1) We destruct QFseventsFileSystemWatcher, which calls FSEventStreamStop
   and FSEventStreamInvalidate/FSEventStreamRelease
2) The FSEvent* calls will happen on the same thread as the destructor
   is being called on, which will be different to the thread that the
   FSEvent* events are popping out on.
3) So, there could be a case where we are in the middle of processing an
   event, but the QFseventsFileSystemWatcher has already died.

The fix is to dispatch the stop/invalidate/release on the queue
associated with the stream.

Patch by Matt Galloway!

Fixes: QTBUG-85594
Pick-to: 5.15 5.12
Change-Id: Ie168bbe91e55c5559632b37bc008e11597e4fdaf
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
bb10
Erik Verbruggen 2020-07-23 18:14:48 +02:00 committed by Thiago Macieira
parent c562c1fc19
commit 6533d1a473
1 changed files with 8 additions and 6 deletions

View File

@ -311,14 +311,16 @@ QFseventsFileSystemWatcherEngine::~QFseventsFileSystemWatcherEngine()
{
QMacAutoReleasePool pool;
// Stop the stream in case we have to wait for the lock below to be acquired.
if (stream)
FSEventStreamStop(stream);
dispatch_sync(queue, ^{
// Stop the stream in case we have to wait for the lock below to be acquired.
if (stream)
FSEventStreamStop(stream);
// The assumption with the locking strategy is that this class cannot and will not be subclassed!
QMutexLocker locker(&lock);
// The assumption with the locking strategy is that this class cannot and will not be subclassed!
QMutexLocker locker(&lock);
stopStream(true);
stopStream(true);
});
dispatch_release(queue);
}