Details
-
Bug
-
Resolution: Unresolved
-
P2: Important
-
None
-
6.3.1
-
None
-
-
b832a5ac7 (dev), 5aca4e09e (tqtc/lts-5.15), 126fe788e (6.3), 58e54dcfd (6.5), 5be8837e2 (6.4), 2e46273e2 (tqtc/lts-6.2)
Description
Returning to a running Qt Android app via Intent while TalkBack is active leads sometimes to a deadlock. It occurs always for me when using a debugger. As far as I can analyze it the following occurs:
1. The App gets woken up by an Intent. A QWindowSystemInterfacePrivate::ApplicationStateChanged event gets processed. This processing ends in QSGThreadedRenderLoop::polishAndSync(), blocking the qtMainLoopThread #1 with a mutex until the QML rendering thread returns (I assume it is a rendering thread, it has no name). The QML rendering thread #2 tries to create a surface in QAndroidPlatformOpenGLWindow::eglSurface() by calling QtAndroid::createSurface() and blocks in a mutex until the call to the Android API returns.
2. In parallel TalkBack tries to get information about the window and calls e.g. androidjniaccessiblity.cpp::descriptionForAccessibleObject() on the Android thread #3. The needed information are gathered from objects living in the main thread #1. Therefor QMetaObject::invokeMethod(_, _, Qt::BlockingQueuedConnection, _) gets called, resulting in a blocked thread waiting on the qtMainLoopThread.
We therefor get a deadlock. I naively tried to add AndroidDeadlockProtector to androidjniaccessiblity.cpp::runInObjectContext, but without luck.
#1 qtMainLoopThread
syscall 0x00000000f31faa1c
__futex_wait_ex(void volatile*, bool, int, bool, timespec const*) 0x00000000f31ffc7e
pthread_cond_wait 0x00000000f3247952
QWaitConditionPrivate::wait(QDeadlineTimer) qwaitcondition_unix.cpp:147
QWaitCondition::wait(QMutex*, QDeadlineTimer) qwaitcondition_unix.cpp:220
QSGThreadedRenderLoop::polishAndSync(QSGThreadedRenderLoop::Window*, bool) qsgthreadedrenderloop.cpp:1555
QSGThreadedRenderLoop::handleExposure(QQuickWindow*) qsgthreadedrenderloop.cpp:1312
QSGThreadedRenderLoop::exposureChanged(QQuickWindow*) qsgthreadedrenderloop.cpp:1232
QQuickWindow::exposeEvent(QExposeEvent*) qquickwindow.cpp:214
QWindow::event(QEvent*) qwindow.cpp:2508
QQuickWindow::event(QEvent*) qquickwindow.cpp:1580
QCoreApplicationPrivate::notify_helper(QObject*, QEvent*) qcoreapplication.cpp:1234
doNotify(QObject*, QEvent*) qcoreapplication.cpp:1163
QCoreApplication::notify(QObject*, QEvent*) qcoreapplication.cpp:1146
QGuiApplication::notify(QObject*, QEvent*) qguiapplication.cpp:1955
QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:1067
QCoreApplication::sendSpontaneousEvent(QObject*, QEvent*) qcoreapplication.cpp:1497
QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::ExposeEvent*) qguiapplication.cpp:3197
QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) qguiapplication.cpp:2094
QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) qwindowsysteminterface.cpp:1137
QWindowSystemInterface::flushWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) qwindowsysteminterface.cpp:1106
QAndroidPlatformWindow::applicationStateChanged(Qt::ApplicationState) qandroidplatformwindow.cpp:205
QAndroidPlatformOpenGLWindow::applicationStateChanged(Qt::ApplicationState) qandroidplatformopenglwindow.cpp:163
QAndroidPlatformScreen::applicationStateChanged(Qt::ApplicationState) qandroidplatformscreen.cpp:352
QtPrivate::FunctorCall<QtPrivate::IndexesList<0>, QtPrivate::List<Qt::ApplicationState>, void, void (QAndroidPlatformScreen::)(Qt::ApplicationState)>::call(void (QAndroidPlatformScreen::)(Qt::ApplicationState), QAndroidPlatformScreen*, void**) qobjectdefs_impl.h:171
void QtPrivate::FunctionPointer<void (QAndroidPlatformScreen::)(Qt::ApplicationState)>::call<QtPrivate::List<Qt::ApplicationState>, void>(void (QAndroidPlatformScreen::)(Qt::ApplicationState), QAndroidPlatformScreen*, void**) qobjectdefs_impl.h:208
QtPrivate::QSlotObject<void (QAndroidPlatformScreen::)(Qt::ApplicationState), QtPrivate::List<Qt::ApplicationState>, void>::impl(int, QtPrivate::QSlotObjectBase, QObject*, void*, bool) qobjectdefs_impl.h:419
QtPrivate::QSlotObjectBase::call(QObject*, void**) qobjectdefs_impl.h:399
void doActivate<false>(QObject*, int, void**) qobject.cpp:3921
QMetaObject::activate(QObject*, QMetaObject const*, int, void**) qobject.cpp:3981
QGuiApplication::applicationStateChanged(Qt::ApplicationState) moc_qguiapplication.cpp:416
QGuiApplicationPrivate::setApplicationState(Qt::ApplicationState, bool) qguiapplication.cpp:3735
QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) qguiapplication.cpp:2060
QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) qwindowsysteminterface.cpp:1137
QUnixEventDispatcherQPA::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) qunixeventdispatcher.cpp:64
QAndroidEventDispatcher::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) qandroideventdispatcher.cpp:99
QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) qeventloop.cpp:136
QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) qeventloop.cpp:218
QCoreApplication::exec() qcoreapplication.cpp:1388
QGuiApplication::exec() qguiapplication.cpp:1887
exec(QScopedPointer<QCoreApplication, QScopedPointerDeleter<QCoreApplication> > const&) Bootstrap.cpp:125
governikus::initApp(int&, char**) Bootstrap.cpp:176
main main.cpp:90
startQtApplication(_JNIEnv*, _jclass*) androidjnimain.cpp:565
art_quick_generic_jni_trampoline 0x00000000ef7620de
art_quick_invoke_stub_internal 0x00000000ef75d5d6
art_quick_invoke_static_stub 0x00000000efb7d610
art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*) 0x00000000ef7b68fc
art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*) 0x00000000ef8ced26
bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x00000000ef8c7158
void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x00000000ef76b0b0
ExecuteSwitchImplAsm 0x00000000ef762c76
art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.llvm.16561771350904891617) 0x00000000ef8c03c0
art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*) 0x00000000ef8c697e
bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x00000000ef8c713e
void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x00000000ef769732
ExecuteSwitchImplAsm 0x00000000ef762c76
art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.llvm.16561771350904891617) 0x00000000ef8c03c0
art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*) 0x00000000ef8c697e
bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x00000000ef8c713e
void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x00000000ef769732
ExecuteSwitchImplAsm 0x00000000ef762c76
art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.llvm.16561771350904891617) 0x00000000ef8c03c0
art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*) 0x00000000ef8c68ba
artQuickToInterpreterBridge 0x00000000efb6040a
art_quick_to_interpreter_bridge 0x00000000ef762164
art_quick_invoke_stub_internal 0x00000000ef75d5d6
art_quick_invoke_stub 0x00000000efb7d4e0
art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*) 0x00000000ef7b68ea
art::JValue art::InvokeVirtualOrInterfaceWithJValues<art::ArtMethod*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, art::ArtMethod*, jvalue const*) 0x00000000efa88794
art::JValue art::InvokeVirtualOrInterfaceWithJValues<_jmethodID*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, jvalue const*) 0x00000000efa888a2
art::Thread::CreateCallback(void*) 0x00000000efacad22
__pthread_start(void*) 0x00000000f324830c
__start_thread 0x00000000f32008f0
#2 Rendering Thread (QtThread)
syscall 0x00000000f31faa1c __futex_wait_ex(void volatile*, bool, int, bool, timespec const*) 0x00000000f31ffc7e pthread_cond_wait 0x00000000f3247952 QWaitConditionPrivate::wait(QDeadlineTimer) qwaitcondition_unix.cpp:147 QWaitCondition::wait(QMutex*, QDeadlineTimer) qwaitcondition_unix.cpp:220 QAndroidPlatformOpenGLWindow::eglSurface(void*) qandroidplatformopenglwindow.cpp:135 QAndroidPlatformOpenGLContext::eglSurfaceForPlatformSurface(QPlatformSurface*) qandroidplatformopenglcontext.cpp:77 QEGLPlatformContext::makeCurrent(QPlatformSurface*) qeglplatformcontext.cpp:387 QAndroidPlatformOpenGLContext::makeCurrent(QPlatformSurface*) qandroidplatformopenglcontext.cpp:71 QOpenGLContext::makeCurrent(QSurface*) qopenglcontext.cpp:670 QRhiGles2::ensureContext(QSurface*) const qrhigles2.cpp:533 QRhiGles2::beginFrame(QRhiSwapChain*, QFlags<QRhi::BeginFrameFlag>) qrhigles2.cpp:1818 QRhi::beginFrame(QRhiSwapChain*, QFlags<QRhi::BeginFrameFlag>) qrhi.cpp:6764 QSGRenderThread::syncAndRender() qsgthreadedrenderloop.cpp:709 QSGRenderThread::run() qsgthreadedrenderloop.cpp:986 QThreadPrivate::start(void*)::$_0::operator()() const qthread_unix.cpp:356 void (anonymous namespace)::terminate_on_exception<QThreadPrivate::start(void*)::$_0>(QThreadPrivate::start(void*)::$_0&&) qthread_unix.cpp:292 QThreadPrivate::start(void*) qthread_unix.cpp:315 __pthread_start(void*) 0x00000000f324830c __start_thread 0x00000000f32008f0
#3 Android Thread (kus.android)
syscall 0x00000000f31faa1c
QtLinuxFutex::_q_futex(int*, int, int, unsigned int, int*, int) qfutex_p.h:121
void QtLinuxFutex::futexWait<QBasicAtomicInteger<unsigned int> >(QBasicAtomicInteger<unsigned int>&, QBasicAtomicInteger<unsigned int>::Type) qfutex_p.h:140
bool futexSemaphoreTryAcquire_loop<false>(QBasicAtomicInteger<unsigned int>&, unsigned int, unsigned int, int) qsemaphore.cpp:206
bool futexSemaphoreTryAcquire<false>(QBasicAtomicInteger<unsigned int>&, int, int) qsemaphore.cpp:262
QSemaphore::acquire(int) qsemaphore.cpp:328
QMetaObject::invokeMethodImpl(QObject*, QtPrivate::QSlotObjectBase*, Qt::ConnectionType, void*) qmetaobject.cpp:1546
std::__ndk1::enable_if<((!(QtPrivate::FunctionPointer<QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv*, _jobject*, int)::$_8>::IsPointerToMemberFunction)) && ((QtPrivate::FunctionPointer<QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv*, _jobject*, int)::$_8>::ArgumentCount) == (-(1)))) && (!(std::is_convertible<QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv*, _jobject*, int)::$_8, char const*>::value)), bool>::type QMetaObject::invokeMethod<QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv*, _jobject*, int)::$_8>(QObject*, QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv*, _jobject*, int)::$_8, Qt::ConnectionType, decltype(fp0())*) qobjectdefs.h:355
void QtAndroidAccessibility::runInObjectContext<QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv*, _jobject*, int)::$_8, QString>(QObject*, QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv*, _jobject*, int)::$_8&&, QString*) androidjniaccessibility.cpp:103
QtAndroidAccessibility::descriptionForAccessibleObject(_JNIEnv*, _jobject*, int) androidjniaccessibility.cpp:584
art_quick_generic_jni_trampoline 0x00000000ef7620de
art_quick_invoke_stub_internal 0x00000000ef75d5d6
art_quick_invoke_static_stub 0x00000000efb7d610
art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*) 0x00000000ef7b68fc
art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*) 0x00000000ef8ced26
bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x00000000ef8c7158
void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x00000000ef76b0b0
ExecuteSwitchImplAsm 0x00000000ef762c76
art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.llvm.16561771350904891617) 0x00000000ef8c03c0
art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*) 0x00000000ef8c697e
bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x00000000ef8c713e
void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x00000000ef76b0b0
ExecuteSwitchImplAsm 0x00000000ef762c76
art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.llvm.16561771350904891617) 0x00000000ef8c03c0
art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*) 0x00000000ef8c697e
bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x00000000ef8c713e
void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x00000000ef769d38
ExecuteSwitchImplAsm 0x00000000ef762c76
art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.llvm.16561771350904891617) 0x00000000ef8c03c0
art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*) 0x00000000ef8c697e
bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x00000000ef8c713e
void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x00000000ef769d38
ExecuteSwitchImplAsm 0x00000000ef762c76
art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.llvm.16561771350904891617) 0x00000000ef8c03c0
art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*) 0x00000000ef8c697e
bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x00000000ef8c713e
void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x00000000ef769d38
ExecuteSwitchImplAsm 0x00000000ef762c76
art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.llvm.16561771350904891617) 0x00000000ef8c03c0
art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*) 0x00000000ef8c697e
bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x00000000ef8c713e
void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x00000000ef769732
ExecuteSwitchImplAsm 0x00000000ef762c76
art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.llvm.16561771350904891617) 0x00000000ef8c03c0
art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*) 0x00000000ef8c697e
bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x00000000ef8c713e
void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x00000000ef76b0b0
ExecuteSwitchImplAsm 0x00000000ef762c76
art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.llvm.16561771350904891617) 0x00000000ef8c03c0
art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*) 0x00000000ef8c697e
bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x00000000ef8c713e
void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x00000000ef769d38
ExecuteSwitchImplAsm 0x00000000ef762c76
art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.llvm.16561771350904891617) 0x00000000ef8c03c0
art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*) 0x00000000ef8c697e
bool art::interpreter::DoCall<false, true>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x00000000ef8c78d6
void art::interpreter::ExecuteSwitchImplCpp<true, false>(art::interpreter::SwitchImplContext*) 0x00000000ef790a10
ExecuteSwitchImplAsm 0x00000000ef762c76
art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.llvm.16561771350904891617) 0x00000000ef8c0296
art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*) 0x00000000ef8c68ba
artQuickToInterpreterBridge 0x00000000efb6040a
art_quick_to_interpreter_bridge 0x00000000ef762164
<unknown> 0x00000000ef762260