Android ANR Deadlock in QtAccessibilityDelegate
-
wrote on 17 Jan 2023, 16:20 last edited by
I'm getting an ANR reported in Google play in a Qt 6.4.1 Qt Quick app. I am not able to reproduce it, but it is causing an ANR rate of about 1% of daily sessions, which is above Google's bad behavior threshold.
The stacktrace on the main Android thread always looks like this:
#00 pc 0x000000000004dc5c /apex/com.android.runtime/lib64/bionic/libc.so (syscall+28) #01 pc 0x000000000042fb24 /data/app/~~VgtqCgcr-t5Si4wwd3VLQw==/com.memorymap.mmfa-5dkeqI6_jo1Ied7dRGlw2A==/lib/arm64/libQt6Core_arm64-v8a.so #02 pc 0x0000000000431250 /data/app/~~VgtqCgcr-t5Si4wwd3VLQw==/com.memorymap.mmfa-5dkeqI6_jo1Ied7dRGlw2A==/lib/arm64/libQt6Core_arm64-v8a.so #03 pc 0x0000000000430f50 /data/app/~~VgtqCgcr-t5Si4wwd3VLQw==/com.memorymap.mmfa-5dkeqI6_jo1Ied7dRGlw2A==/lib/arm64/libQt6Core_arm64-v8a.so #04 pc 0x0000000000340ad4 /data/app/~~VgtqCgcr-t5Si4wwd3VLQw==/com.memorymap.mmfa-5dkeqI6_jo1Ied7dRGlw2A==/lib/arm64/libQt6Core_arm64-v8a.so (QMetaObject::invokeMethodImpl(QObject*, QtPrivate::QSlotObjectBase*, Qt::ConnectionType, void*)+276) #05 pc 0x000000000003bca8 /data/app/~~VgtqCgcr-t5Si4wwd3VLQw==/com.memorymap.mmfa-5dkeqI6_jo1Ied7dRGlw2A==/lib/arm64/libplugins_platforms_qtforandroid_arm64-v8a.so at org.qtproject.qt.android.accessibility.QtNativeAccessibility.populateNode (Native method) at org.qtproject.qt.android.accessibility.QtAccessibilityDelegate.getNodeForVirtualViewId (QtAccessibilityDelegate.java:385) at org.qtproject.qt.android.accessibility.QtAccessibilityDelegate.access$800 (QtAccessibilityDelegate.java:31) at org.qtproject.qt.android.accessibility.QtAccessibilityDelegate$1.createAccessibilityNodeInfo (QtAccessibilityDelegate.java:440) at android.view.ViewRootImpl.requestSendAccessibilityEvent (ViewRootImpl.java:9153) at android.view.ViewGroup.requestSendAccessibilityEvent (ViewGroup.java:1099) at android.view.ViewGroup.requestSendAccessibilityEvent (ViewGroup.java:1099) at android.view.ViewGroup.requestSendAccessibilityEvent (ViewGroup.java:1099) at org.qtproject.qt.android.accessibility.QtAccessibilityDelegate.sendAccessibilityEvent (QtAccessibilityDelegate.java:255) at org.qtproject.qt.android.accessibility.QtAccessibilityDelegate.sendEventForVirtualViewId (QtAccessibilityDelegate.java:241) at org.qtproject.qt.android.accessibility.QtAccessibilityDelegate.notifyObjectFocus (QtAccessibilityDelegate.java:199) at org.qtproject.qt.android.QtActivityDelegate.notifyObjectFocus (QtActivityDelegate.java:936) at org.qtproject.qt.android.QtNative$17.run (QtNative.java:970) at android.os.Handler.handleCallback (Handler.java:938) at android.os.Handler.dispatchMessage (Handler.java:99) at android.os.Looper.loopOnce (Looper.java:346) at android.os.Looper.loop (Looper.java:475) at android.app.ActivityThread.main (ActivityThread.java:7889) at java.lang.reflect.Method.invoke (Native method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1009)
The qtMainLoopThread has various different stacktraces in different instances of the ANR. Here's a typical one.
#00 pc 0x000000000004e1dc /apex/com.android.runtime/lib64/bionic/libc.so (syscall+28) #01 pc 0x00000000000529b8 /apex/com.android.runtime/lib64/bionic/libc.so (__futex_wait_ex(void volatile*, bool, int, bool, timespec const*)+144) #02 pc 0x00000000000b5ac4 /apex/com.android.runtime/lib64/bionic/libc.so (pthread_cond_wait+76) #03 pc 0x0000000000436690 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Core_arm64-v8a.so #04 pc 0x000000000043662c /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Core_arm64-v8a.so (QWaitCondition::wait(QMutex*, QDeadlineTimer)+52) #05 pc 0x00000000005133a8 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Quick_arm64-v8a.so #06 pc 0x0000000000512e40 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Quick_arm64-v8a.so #07 pc 0x0000000000512b68 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Quick_arm64-v8a.so #08 pc 0x000000000038baf8 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Gui_arm64-v8a.so (QWindow::event(QEvent*)+720) #09 pc 0x00000000003cee7c /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Quick_arm64-v8a.so (QQuickWindow::event(QEvent*)+2504) #10 pc 0x0000000000335bd0 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Core_arm64-v8a.so #11 pc 0x0000000000335b4c /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Core_arm64-v8a.so (QCoreApplication::notifyInternal2(QObject*, QEvent*)+176) #12 pc 0x000000000034f918 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Gui_arm64-v8a.so (QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::ExposeEvent*)+308) #13 pc 0x000000000034d348 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Gui_arm64-v8a.so (QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*)+152) #14 pc 0x00000000003903f8 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Gui_arm64-v8a.so (QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>)+120) #15 pc 0x0000000000390250 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Gui_arm64-v8a.so (QWindowSystemInterface::flushWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>)+172) #16 pc 0x0000000000067808 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libplugins_platforms_qtforandroid_arm64-v8a.so #17 pc 0x000000000005e87c /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libplugins_platforms_qtforandroid_arm64-v8a.so #18 pc 0x000000000005f05c /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libplugins_platforms_qtforandroid_arm64-v8a.so #19 pc 0x000000000036aa88 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Core_arm64-v8a.so #20 pc 0x00000000003516a8 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Gui_arm64-v8a.so (QGuiApplication::applicationStateChanged(Qt::ApplicationState)+36) #21 pc 0x000000000034f2e0 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Gui_arm64-v8a.so (QGuiApplicationPrivate::setApplicationState(Qt::ApplicationState, bool)+140) #22 pc 0x000000000034d3b8 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Gui_arm64-v8a.so (QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*)+264) #23 pc 0x00000000003903f8 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Gui_arm64-v8a.so (QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>)+120) #24 pc 0x00000000005debe4 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Gui_arm64-v8a.so (QUnixEventDispatcherQPA::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)+32) #25 pc 0x000000000004e428 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libplugins_platforms_qtforandroid_arm64-v8a.so #26 pc 0x000000000033ca8c /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Core_arm64-v8a.so (QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>)+332) #27 pc 0x00000000003360c4 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libQt6Core_arm64-v8a.so (QCoreApplication::exec()+136) #28 pc 0x0000000000426660 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libMMfA_arm64-v8a.so (main+1764) #29 pc 0x00000000000444a0 /data/app/~~ABusX6UujVHgfORfwFkH8A==/com.memorymap.mmfa-XU5ReIfOgsoQipxAgj_9MQ==/lib/arm64/libplugins_platforms_qtforandroid_arm64-v8a.so at org.qtproject.qt.android.QtNative.startQtApplication (Native method) at org.qtproject.qt.android.QtNative$7.run (QtNative.java:622) at org.qtproject.qt.android.QtThread$1.run (QtThread.java:25) at java.lang.Thread.run (Thread.java:1012)
Other threads seem to be in the normal "ready" state. None the threads are executing my code (linked into libMMfA_arm64-v8a.so) except for main calling QCoreApplication::exec(). That doesn't exonerate my code, but it makes it hard to debug!
I wonder if anyone else is seeing this ANR? Any hints on how to fix it or avoid it?
What is org.qtproject.qt.android.accessibility.QtAccessibilityDelegate? Is this only invoked if the user has selected a screen reader or something like that, or is it run all the time? Any insight would be greatly appreciated.
-
wrote on 19 Jan 2023, 22:38 last edited by
Looking at the Qt source code, the problem is in plugins/platforms/android/androidjniaccessibility.cpp,
template <typename Func, typename Ret> void runInObjectContext(QObject *context, Func &&func, Ret *retVal) { if (!QtAndroid::blockEventLoopsWhenSuspended() || QGuiApplication::applicationState() != Qt::ApplicationSuspended) { QMetaObject::invokeMethod(context, func, Qt::BlockingQueuedConnection, retVal); } else { __android_log_print(ANDROID_LOG_WARN, m_qtTag, "Could not run accessibility call in object context, event loop suspended."); } }
There could also be a race condition in the applicationState tests. But in my app I have <meta-data android:name="android.app.background_running" android:value="true"/> so I don't think the applicationState matters in my case.
In any case, it is blocking the Android main thread to run code on a QObject's thread. There must be other places where the Qt threads block waiting for the Android main thread, causing deadlock.
I will submit this as a bug report.
-
wrote on 23 Jan 2023, 19:49 last edited by Dmitriano
I also have an ANR in my app at
QMetaObject::invokeMethodImpl
with the following stack trace:Thread "main" tid=1 Native #00 pc 0x000000000001edac /system/lib64/libc.so (syscall+28) #01 pc 0x0000000000429318 /data/app/net.geographx.LinesGame-go3lICl-TceQVuAnsbM5xw==/lib/arm64/libQt6Core_arm64-v8a.so #02 pc 0x000000000042aa24 /data/app/net.geographx.LinesGame-go3lICl-TceQVuAnsbM5xw==/lib/arm64/libQt6Core_arm64-v8a.so #03 pc 0x000000000042a710 /data/app/net.geographx.LinesGame-go3lICl-TceQVuAnsbM5xw==/lib/arm64/libQt6Core_arm64-v8a.so #04 pc 0x000000000033abcc /data/app/net.geographx.LinesGame-go3lICl-TceQVuAnsbM5xw==/lib/arm64/libQt6Core_arm64-v8a.so (QMetaObject::invokeMethodImpl(QObject*, QtPrivate::QSlotObjectBase*, Qt::ConnectionType, void*)+296) #05 pc 0x000000000003b8a4 /data/app/net.geographx.LinesGame-go3lICl-TceQVuAnsbM5xw==/lib/arm64/libplugins_platforms_qtforandroid_arm64-v8a.so at org.qtproject.qt.android.accessibility.QtNativeAccessibility.childIdListForAccessibleObject (Native method) at org.qtproject.qt.android.accessibility.QtAccessibilityDelegate.getNodeForView (QtAccessibilityDelegate.java:354) at org.qtproject.qt.android.accessibility.QtAccessibilityDelegate.access$700 (QtAccessibilityDelegate.java:31) at org.qtproject.qt.android.accessibility.QtAccessibilityDelegate$1.createAccessibilityNodeInfo (QtAccessibilityDelegate.java:438) at android.view.ViewRootImpl.handleWindowContentChangedEvent (ViewRootImpl.java:8686) at android.view.ViewRootImpl.requestSendAccessibilityEvent (ViewRootImpl.java:8616) at android.view.ViewGroup.requestSendAccessibilityEvent (ViewGroup.java:1060) at android.view.ViewGroup.requestSendAccessibilityEvent (ViewGroup.java:1060) at android.view.ViewGroup.requestSendAccessibilityEvent (ViewGroup.java:1060) at android.view.View.sendAccessibilityEventUncheckedInternal (View.java:7574) at android.view.View.sendAccessibilityEventUnchecked (View.java:7546) at android.view.ViewRootImpl$SendWindowContentChangedAccessibilityEvent.run (ViewRootImpl.java:9528) at android.view.ViewRootImpl$SendWindowContentChangedAccessibilityEvent.removeCallbacksAndRun (ViewRootImpl.java:9583) at android.view.ViewRootImpl.requestSendAccessibilityEvent (ViewRootImpl.java:8578) at android.view.View.sendAccessibilityEventUncheckedInternal (View.java:7574) at android.view.View.sendAccessibilityEventUnchecked (View.java:7546) at android.view.View.sendAccessibilityEventInternal (View.java:7523) at android.view.View.sendAccessibilityEvent (View.java:7490) at com.android.internal.policy.DecorView.sendAccessibilityEvent (DecorView.java:679) at android.view.ViewRootImpl.performTraversals (ViewRootImpl.java:2971) at android.view.ViewRootImpl.doTraversal (ViewRootImpl.java:1804) at android.view.ViewRootImpl$TraversalRunnable.run (ViewRootImpl.java:8218) at android.view.Choreographer$CallbackRecord.run (Choreographer.java:1047) at android.view.Choreographer.doCallbacks (Choreographer.java:859) at android.view.Choreographer.doFrame (Choreographer.java:791) at android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:1033) at android.os.Handler.handleCallback (Handler.java:873) at android.os.Handler.dispatchMessage (Handler.java:99) at android.os.Looper.loop (Looper.java:233) at android.app.ActivityThread.main (ActivityThread.java:7212) at java.lang.reflect.Method.invoke (Native method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:499) at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:965)
-
wrote on 23 Jan 2023, 20:15 last edited by
Looks like the same issue.
I am rolling out an update that adds
qputenv("QT_ANDROID_DISABLE_ACCESSIBILITY", "1");
in my app's main function before the construction of the QGuiApplication. I will know in a month or so whether this avoids the problem. -
wrote on 3 Feb 2023, 20:13 last edited by
@bee65 said in Android ANR Deadlock in QtAccessibilityDelegate:
Looks like the same issue.
I am rolling out an update that adds
qputenv("QT_ANDROID_DISABLE_ACCESSIBILITY", "1");
in my app's main function before the construction of the QGuiApplication. I will know in a month or so whether this avoids the problem.So far, I have had zero ANRs in the new update with this change, rolled out to about 3000 users.
-
@bee65 said in Android ANR Deadlock in QtAccessibilityDelegate:
Looks like the same issue.
I am rolling out an update that adds
qputenv("QT_ANDROID_DISABLE_ACCESSIBILITY", "1");
in my app's main function before the construction of the QGuiApplication. I will know in a month or so whether this avoids the problem.So far, I have had zero ANRs in the new update with this change, rolled out to about 3000 users.
wrote on 1 May 2023, 17:48 last edited byI can confirm this issue.
Will try @beamide solution and post back in some weeks. -
wrote on 15 May 2024, 07:48 last edited by
Hi guys, did the environment variable help you to get rid of these ANRs? Didn't it backfire somewhere else?