Details
-
Bug
-
Resolution: Fixed
-
P2: Important
-
6.0, 6.5.3, dev
-
None
-
59e21a536 (dev), f89d80c90 (6.7), d5528cdec (6.6)
Description
To reproduce:
- Obtain a future from QtConcurrent::run()
- Add a continuation with a context object that belongs to the main thread
- Call QFuture::waitForFinished on the main thread
Expected result:
3: waitForFinished completes
Actual result:
3: waitForFinished deadlocks occasionally
Reason for deadlock
QFuture::waitForFinished() calls QFutureInterfaceBase::reportFinished() which locks a QMutex. Further down the callstack, T QFutureInterface<T>::takeResult() again locks the same mutex inside the call to Q_ASSERT(isValid());
ntdll.dll!00007ffeefaf2e54() Unknown ntdll.dll!00007ffeefa839c5() Unknown ntdll.dll!00007ffeefa9f9bc() Unknown ntdll.dll!00007ffeefa9ba83() Unknown KernelBase.dll!00007ffeed0f2773() Unknown Qt6Cored.dll!QtWindowsFutex::futexWait<QBasicAtomicPointer<QMutexPrivate>>(QBasicAtomicPointer<QMutexPrivate> & futex, QMutexPrivate * expectedValue) Line 36 C++ Qt6Cored.dll!QBasicMutex::lockInternal() Line 650 C++ Qt6Cored.dll!QBasicMutex::lock() Line 43 C++ Qt6Cored.dll!QMutexLocker<QMutex>::QMutexLocker<QMutex>(QMutex * mutex) Line 224 C++ Qt6Cored.dll!QFutureInterfaceBase::isValid() Line 326 C++ ffmpegmediaplugind.dll!QFutureInterface<QMaybe<QFFmpeg::MediaDataHolder,QFFmpeg::MediaDataHolder::ContextError>>::takeResult() Line 421 C++ ffmpegmediaplugind.dll!QFuture<QMaybe<QFFmpeg::MediaDataHolder,QFFmpeg::MediaDataHolder::ContextError>>::takeResult<QMaybe<QFFmpeg::MediaDataHolder,QFFmpeg::MediaDataHolder::ContextError>,void>() Line 117 C++ ffmpegmediaplugind.dll!QtPrivate::Continuation<`QFFmpeg::PlaybackEngine::setMedia'::`2'::<lambda_2>,void,QMaybe<QFFmpeg::MediaDataHolder,QFFmpeg::MediaDataHolder::ContextError>>::fulfillVoidPromise() Line 642 C++ ffmpegmediaplugind.dll!QtPrivate::Continuation<`QFFmpeg::PlaybackEngine::setMedia'::`2'::<lambda_2>,void,QMaybe<QFFmpeg::MediaDataHolder,QFFmpeg::MediaDataHolder::ContextError>>::runFunction() Line 460 C++ ffmpegmediaplugind.dll!QtPrivate::SyncContinuation<`QFFmpeg::PlaybackEngine::setMedia'::`2'::<lambda_2>,void,QMaybe<QFFmpeg::MediaDataHolder,QFFmpeg::MediaDataHolder::ContextError>>::runImpl() Line 346 C++ ffmpegmediaplugind.dll!QtPrivate::Continuation<`QFFmpeg::PlaybackEngine::setMedia'::`2'::<lambda_2>,void,QMaybe<QFFmpeg::MediaDataHolder,QFFmpeg::MediaDataHolder::ContextError>>::execute() Line 492 C++ ffmpegmediaplugind.dll!QtPrivate::Continuation<`QFFmpeg::PlaybackEngine::setMedia'::`2'::<lambda_2>,void,QMaybe<QFFmpeg::MediaDataHolder,QFFmpeg::MediaDataHolder::ContextError>>::create::__l2::<lambda_1>::operator()() Line 622 C++ ffmpegmediaplugind.dll!QtPrivate::FunctorCall<QtPrivate::IndexesList<>,QtPrivate::List<>,void,`QtPrivate::Continuation<`QFFmpeg::PlaybackEngine::setMedia'::`2'::<lambda_2>,void,QMaybe<QFFmpeg::MediaDataHolder,QFFmpeg::MediaDataHolder::ContextError>>::create<`QFFmpeg::PlaybackEngine::setMedia'::`2'::<lambda_2>>'::`2'::<lambda_1>>::call(QtPrivate::Continuation<`QFFmpeg::PlaybackEngine::setMedia'::`2'::<lambda_2>,void,QMaybe<QFFmpeg::MediaDataHolder,QFFmpeg::MediaDataHolder::ContextError>>::create::__l2::<lambda_1> & f, void * * arg) Line 137 C++ ffmpegmediaplugind.dll!QtPrivate::Functor<`QtPrivate::Continuation<`QFFmpeg::PlaybackEngine::setMedia'::`2'::<lambda_2>,void,QMaybe<QFFmpeg::MediaDataHolder,QFFmpeg::MediaDataHolder::ContextError>>::create<`QFFmpeg::PlaybackEngine::setMedia'::`2'::<lambda_2>>'::`2'::<lambda_1>,0>::call<QtPrivate::List<>,void>(QtPrivate::Continuation<`QFFmpeg::PlaybackEngine::setMedia'::`2'::<lambda_2>,void,QMaybe<QFFmpeg::MediaDataHolder,QFFmpeg::MediaDataHolder::ContextError>>::create::__l2::<lambda_1> & f, void * __formal, void * * arg) Line 340 C++ ffmpegmediaplugind.dll!QtPrivate::QCallableObject<`QtPrivate::Continuation<`QFFmpeg::PlaybackEngine::setMedia'::`2'::<lambda_2>,void,QMaybe<QFFmpeg::MediaDataHolder,QFFmpeg::MediaDataHolder::ContextError>>::create<`QFFmpeg::PlaybackEngine::setMedia'::`2'::<lambda_2>>'::`2'::<lambda_1>,QtPrivate::List<>,void>::impl(int which, QtPrivate::QSlotObjectBase * this_, QObject * r, void * * a, bool * ret) Line 570 C++ Qt6Cored.dll!QtPrivate::QSlotObjectBase::call(QObject * r, void * * a) Line 472 C++ Qt6Cored.dll!QtPrivate::watchContinuationImpl::__l2::<lambda_1>::operator()() Line 132 C++ Qt6Cored.dll!QtPrivate::FunctorCall<QtPrivate::IndexesList<>,QtPrivate::List<>,void,`QtPrivate::watchContinuationImpl'::`2'::<lambda_1>>::call(QtPrivate::watchContinuationImpl::__l2::<lambda_1> & f, void * * arg) Line 137 C++ Qt6Cored.dll!QtPrivate::Functor<`QtPrivate::watchContinuationImpl'::`2'::<lambda_1>,0>::call<QtPrivate::List<>,void>(QtPrivate::watchContinuationImpl::__l2::<lambda_1> & f, void * __formal, void * * arg) Line 340 C++ Qt6Cored.dll!QtPrivate::QCallableObject<`QtPrivate::watchContinuationImpl'::`2'::<lambda_1>,QtPrivate::List<>,void>::impl(int which, QtPrivate::QSlotObjectBase * this_, QObject * r, void * * a, bool * ret) Line 570 C++ Qt6Cored.dll!QtPrivate::QSlotObjectBase::call(QObject * r, void * * a) Line 472 C++ Qt6Cored.dll!doActivate<0>(QObject * sender, int signal_index, void * * argv) Line 4039 C++ Qt6Cored.dll!QMetaObject::activate(QObject * sender, const QMetaObject * m, int local_signal_index, void * * argv) Line 4100 C++ Qt6Cored.dll!QBasicFutureWatcher::finished() Line 140 C++ Qt6Cored.dll!QBasicFutureWatcher::event(QEvent * event) Line 109 C++ Qt6Cored.dll!QCoreApplicationPrivate::notify_helper(QObject * receiver, QEvent * event) Line 1305 C++ Qt6Cored.dll!doNotify(QObject * receiver, QEvent * event) Line 1232 C++ Qt6Cored.dll!QCoreApplication::notify(QObject * receiver, QEvent * event) Line 1216 C++ Qt6Guid.dll!QGuiApplication::notify(QObject * object, QEvent * event) Line 1994 C++ Qt6Cored.dll!QCoreApplication::notifyInternal2(QObject * receiver, QEvent * event) Line 1131 C++ Qt6Cored.dll!QCoreApplication::sendEvent(QObject * receiver, QEvent * event) Line 1573 C++ Qt6Cored.dll!QBasicFutureWatcher::postCallOutEvent(const QFutureCallOutEvent & event) Line 73 C++ Qt6Cored.dll!QFutureInterfaceBasePrivate::sendCallOut(const QFutureCallOutEvent & callOutEvent) Line 825 C++ Qt6Cored.dll!QFutureInterfaceBase::reportFinished() Line 477 C++ ffmpegmediaplugind.dll!QFutureInterface<QMaybe<QFFmpeg::MediaDataHolder,QFFmpeg::MediaDataHolder::ContextError>>::reportFinished() Line 254 C++ ffmpegmediaplugind.dll!QtConcurrent::RunFunctionTaskBase<QMaybe<QFFmpeg::MediaDataHolder,QFFmpeg::MediaDataHolder::ContextError>>::run() Line 92 C++ Qt6Cored.dll!QThreadPoolPrivate::stealAndRunRunnable(QRunnable * runnable) Line 380 C++ Qt6Cored.dll!QFutureInterfaceBase::waitForFinished() Line 539 C++ ffmpegmediaplugind.dll!QFuture<QMaybe<QFFmpeg::MediaDataHolder,QFFmpeg::MediaDataHolder::ContextError>>::waitForFinished() Line 102 C++ > ffmpegmediaplugind.dll!QFFmpeg::PlaybackEngine::~PlaybackEngine() Line 57 C++ ffmpegmediaplugind.dll!QFFmpeg::PlaybackEngine::`scalar deleting destructor'(unsigned int) C++
Attachments
Issue Links
- duplicates
-
QTBUG-119406 QFuture::then() with context object deadlocks
-
- Closed
-
- resulted from
-
QTBUG-83389 QFutureInterface: takeResult() should either require a type to be default-constructible or return std::optional
-
- Closed
-
For Gerrit Dashboard: QTBUG-117918 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
520860,15 | QFuture: Don't use QFutureCallOutInterface for continuations | dev | qt/qtbase | Status: MERGED | +2 | 0 |
525172,2 | QFuture: Don't use QFutureCallOutInterface for continuations | 6.7 | qt/qtbase | Status: MERGED | +2 | 0 |
525292,2 | QFuture: Don't use QFutureCallOutInterface for continuations | 6.6 | qt/qtbase | Status: MERGED | +2 | 0 |