Details
-
Bug
-
Resolution: Unresolved
-
P1: Critical
-
None
-
6.6, 6.7, 6.8
-
-
2025wk22s1-2QtforAndroid
Description
Sometimes when invoking
QNativeInterface::QAndroidApplication::runOnAndroidMainThread([](){
// ...
}).waitForFinished();
an Android application may freeze.
The main issue seems to be that some accessibility events may be created while the Qt thread is waiting for the Android thread.
At the same time accessibility events themselves end up invoking a method on the Qt thread through a BlockingQueuedConnection, leaving the two threads waiting on each other, if the two events happen with the wrong timing.
Attached is a minimum reproducible example I created that freezes on my phone.
Please note that on other phones it doesn't freeze, and I couldn't understand why.
Here's the stack trace of the two threads when the attached project freezes:
Android Thread
1 syscall (aarch64) C:\Users\aless\Documents\test_freezing_android\build\Android_Qt_6_8_0_android_qt_6_8_0_Clang_arm64_v8a-Debug\android-app-process\libc.so 0x75a58b8800 2 QtLinuxFutex::_q_futex(int *, int, int, unsigned long long, int *, int) qfutex_linux_p.h 48 0x72759ee95c 3 void QtLinuxFutex::futexWait<QBasicAtomicInteger<unsigned int>>(QBasicAtomicInteger<unsigned int>&, QBasicAtomicInteger<unsigned int>::Type) qfutex_linux_p.h 67 0x72759f511c 4 bool futexSemaphoreTryAcquire_loop<false>(QBasicAtomicInteger<unsigned long long>&, unsigned long long, unsigned long long, QDeadlineTimer) qsemaphore.cpp 174 0x72759f4668 5 bool futexSemaphoreTryAcquire<QDeadlineTimer::ForeverConstant>(QBasicAtomicInteger<unsigned long long>&, int, QDeadlineTimer::ForeverConstant) qsemaphore.cpp 239 0x72759f3d24 6 QSemaphore::acquire(int) qsemaphore.cpp 327 0x72759f3b04 7 QMetaObject::invokeMethodImpl(QObject *, QtPrivate::QSlotObjectBase *, Qt::ConnectionType, long long, void const * const *, const char * const *, QtPrivate::QMetaTypeInterface const * const *) qmetaobject.cpp 1663 0x72756bb0f8 8 bool QMetaObject::invokeMethodCallableHelper<QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv *, _jobject *, int)::$_0&>(QtPrivate::ContextTypeForFunctor<QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv *, _jobject *, int)::$_0&, void>::ContextType *, QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv *, _jobject *, int)::$_0&, Qt::ConnectionType, QMetaMethodReturnArgument const&) qobjectdefs.h 624 0x724faf6488 9 std::__ndk1::enable_if<!std::disjunction_v<std::__ndk1::is_convertible<QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv *, _jobject *, int)::$_0&, const char *>, std::__ndk1::disjunction<>>, bool>::type QMetaObject::invokeMethod<QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv *, _jobject *, int)::$_0&>(QtPrivate::ContextTypeForFunctor<QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv *, _jobject *, int)::$_0&, void>::ContextType *, QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv *, _jobject *, int)::$_0&, Qt::ConnectionType, QTemplatedMetaMethodReturnArgument<QtPrivate::Callable<QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv *, _jobject *, int)::$_0&>::ReturnType>) qobjectdefs.h 469 0x724faf6308 10 std::__ndk1::enable_if<!std::disjunction_v<std::__ndk1::is_convertible<QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv *, _jobject *, int)::$_0&, const char *>, std::__ndk1::disjunction<std::__ndk1::is_base_of<QGenericArgument, QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv *, _jobject *, int)::$_0&>>>, bool>::type QMetaObject::invokeMethod<QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv *, _jobject *, int)::$_0&>(QtPrivate::ContextTypeForFunctor<QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv *, _jobject *, int)::$_0&, void>::ContextType *, QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv *, _jobject *, int)::$_0&, Qt::ConnectionType, QtPrivate::Callable<QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv *, _jobject *, int)::$_0&>::ReturnType *) qobjectdefs.h 446 0x724faf62ac 11 void QtAndroidAccessibility::runInObjectContext<QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv *, _jobject *, int)::$_0, QString>(QObject *, QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv *, _jobject *, int)::$_0&&, QString *) androidjniaccessibility.cpp 78 0x724faf61d8 12 QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv *, _jobject *, int) androidjniaccessibility.cpp 460 0x724faf1a1c 13 art_quick_generic_jni_trampoline (aarch64) C:\Users\aless\.lldb\module_cache\remote-android\.cache\02BEC594-0BE7-04B8-63F6-514FC7D81C41\libart.so 0x72f6d7a634 14 art_quick_invoke_static_stub (aarch64) C:\Users\aless\.lldb\module_cache\remote-android\.cache\02BEC594-0BE7-04B8-63F6-514FC7D81C41\libart.so 0x72f6d63e84 15 bool art::interpreter::DoCall<false>(art::ArtMethod *, art::Thread *, art::ShadowFrame&, art::Instruction const *, unsigned short, bool, art::JValue *) (aarch64) C:\Users\aless\.lldb\module_cache\remote-android\.cache\02BEC594-0BE7-04B8-63F6-514FC7D81C41\libart.so 0x72f6f37bac 16 void art::interpreter::ExecuteSwitchImplCpp<false>(art::interpreter::SwitchImplContext *) (aarch64) C:\Users\aless\.lldb\module_cache\remote-android\.cache\02BEC594-0BE7-04B8-63F6-514FC7D81C41\libart.so 0x72f6ebb1e0 17 ExecuteSwitchImplAsm (aarch64) C:\Users\aless\.lldb\module_cache\remote-android\.cache\02BEC594-0BE7-04B8-63F6-514FC7D81C41\libart.so 0x72f6d7cddc 18 art::interpreter::Execute(art::Thread *, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.__uniq.112435418011751916792819755956732575238.llvm.8722505846101882172) (aarch64) C:\Users\aless\.lldb\module_cache\remote-android\.cache\02BEC594-0BE7-04B8-63F6-514FC7D81C41\libart.so 0x72f6d96b18 19 bool art::interpreter::DoCall<false>(art::ArtMethod *, art::Thread *, art::ShadowFrame&, art::Instruction const *, unsigned short, bool, art::JValue *) (aarch64) C:\Users\aless\.lldb\module_cache\remote-android\.cache\02BEC594-0BE7-04B8-63F6-514FC7D81C41\libart.so 0x72f6f386f4 20 void art::interpreter::ExecuteSwitchImplCpp<false>(art::interpreter::SwitchImplContext *) (aarch64) C:\Users\aless\.lldb\module_cache\remote-android\.cache\02BEC594-0BE7-04B8-63F6-514FC7D81C41\libart.so 0x72f6ebb2a8 21 ExecuteSwitchImplAsm (aarch64) C:\Users\aless\.lldb\module_cache\remote-android\.cache\02BEC594-0BE7-04B8-63F6-514FC7D81C41\libart.so 0x72f6d7cddc 22 art::interpreter::Execute(art::Thread *, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.__uniq.112435418011751916792819755956732575238.llvm.8722505846101882172) (aarch64) C:\Users\aless\.lldb\module_cache\remote-android\.cache\02BEC594-0BE7-04B8-63F6-514FC7D81C41\libart.so 0x72f6d96b18 23 bool art::interpreter::DoCall<false>(art::ArtMethod *, art::Thread *, art::ShadowFrame&, art::Instruction const *, unsigned short, bool, art::JValue *) (aarch64) C:\Users\aless\.lldb\module_cache\remote-android\.cache\02BEC594-0BE7-04B8-63F6-514FC7D81C41\libart.so 0x72f6f386f4 24 void art::interpreter::ExecuteSwitchImplCpp<false>(art::interpreter::SwitchImplContext *) (aarch64) C:\Users\aless\.lldb\module_cache\remote-android\.cache\02BEC594-0BE7-04B8-63F6-514FC7D81C41\libart.so 0x72f6ebae70 25 ExecuteSwitchImplAsm (aarch64) C:\Users\aless\.lldb\module_cache\remote-android\.cache\02BEC594-0BE7-04B8-63F6-514FC7D81C41\libart.so 0x72f6d7cddc 26 art::interpreter::Execute(art::Thread *, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.__uniq.112435418011751916792819755956732575238.llvm.8722505846101882172) (aarch64) C:\Users\aless\.lldb\module_cache\remote-android\.cache\02BEC594-0BE7-04B8-63F6-514FC7D81C41\libart.so 0x72f6d96b18 27 bool art::interpreter::DoCall<false>(art::ArtMethod *, art::Thread *, art::ShadowFrame&, art::Instruction const *, unsigned short, bool, art::JValue *) (aarch64) C:\Users\aless\.lldb\module_cache\remote-android\.cache\02BEC594-0BE7-04B8-63F6-514FC7D81C41\libart.so 0x72f6f386f4 28 void art::interpreter::ExecuteSwitchImplCpp<false>(art::interpreter::SwitchImplContext *) (aarch64) C:\Users\aless\.lldb\module_cache\remote-android\.cache\02BEC594-0BE7-04B8-63F6-514FC7D81C41\libart.so 0x72f6ebae70 29 ExecuteSwitchImplAsm (aarch64) C:\Users\aless\.lldb\module_cache\remote-android\.cache\02BEC594-0BE7-04B8-63F6-514FC7D81C41\libart.so 0x72f6d7cddc 30 art::interpreter::Execute(art::Thread *, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.__uniq.112435418011751916792819755956732575238.llvm.8722505846101882172) (aarch64) C:\Users\aless\.lldb\module_cache\remote-android\.cache\02BEC594-0BE7-04B8-63F6-514FC7D81C41\libart.so 0x72f6d96b18 ... <More>
Qt thread
1 syscall (aarch64) C:\Users\aless\Documents\test_freezing_android\build\Android_Qt_6_8_0_android_qt_6_8_0_Clang_arm64_v8a-Debug\android-app-process\libc.so 0x75a58b8800 2 __futex_wait_ex(void volatile *, bool, int, bool, timespec const *) (aarch64) C:\Users\aless\Documents\test_freezing_android\build\Android_Qt_6_8_0_android_qt_6_8_0_Clang_arm64_v8a-Debug\android-app-process\libc.so 0x75a58bd564 3 pthread_cond_wait (aarch64) C:\Users\aless\Documents\test_freezing_android\build\Android_Qt_6_8_0_android_qt_6_8_0_Clang_arm64_v8a-Debug\android-app-process\libc.so 0x75a59239f8 4 QWaitConditionPrivate::wait(QDeadlineTimer) qwaitcondition_unix.cpp 102 0x7275a07660 5 QWaitCondition::wait(QMutex *, QDeadlineTimer) qwaitcondition_unix.cpp 180 0x7275a07594 6 QFutureInterfaceBase::waitForFinished() qfutureinterface.cpp 508 0x7275a0c41c 7 QFuture<void>::waitForFinished() qfuture.h 102 0x72e0669354 8 ExampleItem::ExampleItem(QQuickItem *) ExampleItem.cpp 13 0x72e0668fa8 9 QQmlPrivate::QQmlElement<ExampleItem>::QQmlElement() qqmlprivate.h 99 0x72e066e740 10 void QQmlPrivate::createInto<ExampleItem>(void *, void *) qqmlprivate.h 174 0x72e066d03c 11 QQmlType::create(void * *, unsigned long) const qqmltype.cpp 506 0x7268ece210 12 QQmlType::createWithQQmlData() const qqmltype.cpp 521 0x7268ece388 13 QQmlObjectCreator::createInstance(int, QObject *, bool) qqmlobjectcreator.cpp 1301 0x7268e2fec8 14 QQmlObjectCreator::create(int, QObject *, QQmlInstantiationInterrupt *, int) qqmlobjectcreator.cpp 201 0x7268e2f7ac 15 QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt&) qqmlincubator.cpp 286 0x7268dcf108 16 QQmlEnginePrivate::incubate(QQmlIncubator&, QQmlRefPointer<QQmlContextData> const&) qqmlincubator.cpp 53 0x7268dceae0 17 QQmlComponent::create(QQmlIncubator&, QQmlContext *, QQmlContext *) qqmlcomponent.cpp 1494 0x7268d41ed8 18 QQuickLoaderPrivate::_q_sourceLoaded() qquickloader.cpp 734 0x7261562b44 19 QQuickLoaderPrivate::load() qquickloader.cpp 604 0x72615621ac 20 QQuickLoader::loadFromSourceComponent() qquickloader.cpp 476 0x7261561d28 21 QQuickLoader::setSourceComponent(QQmlComponent *) qquickloader.cpp 454 0x72615623b8 22 QQuickLoader::qt_static_metacall(QObject *, QMetaObject::Call, int, void * *) moc_qquickloader_p.cpp 322 0x726156429c 23 QQuickLoader::qt_metacall(QMetaObject::Call, int, void * *) moc_qquickloader_p.cpp 366 0x72615645d0 24 void QQmlPropertyData::doMetacall<(QMetaObject::Call)2>(QObject *, int, void * *) const qqmlpropertydata_p.h 369 0x7268cf8fb0 25 QQmlPropertyData::writeProperty(QObject *, void *, QFlags<QQmlPropertyData::WriteFlag>) const qqmlpropertydata_p.h 387 0x7268cf8e7c 26 QQmlPropertyPrivate::write(QObject *, QQmlPropertyData const&, QVariant const&, QQmlRefPointer<QQmlContextData> const&, QFlags<QQmlPropertyData::WriteFlag>) qqmlproperty.cpp 1535 0x7268e85ca4 27 QV4::QObjectWrapper::setProperty(QV4::ExecutionEngine *, QObject *, QQmlPropertyData const *, QV4::Value const&) qv4qobjectwrapper.cpp 766 0x7268baba08 28 QV4::QObjectWrapper::setQmlProperty(QV4::ExecutionEngine *, QQmlRefPointer<QQmlContextData> const&, QObject *, QV4::String *, QFlags<QV4::QObjectWrapper::Flag>, QV4::Value const&) qv4qobjectwrapper.cpp 555 0x7268baa0a4 29 QV4::QObjectWrapper::virtualPut(QV4::Managed *, QV4::PropertyKey, QV4::Value const&, QV4::Value *) qv4qobjectwrapper.cpp 953 0x7268bae1cc 30 QV4::Object::put(QV4::PropertyKey, QV4::Value const&, QV4::Value *) qv4object_p.h 287 0x7268a602b0 ... <More>