From 1215f61a1ff3f6d86db2410895b83540838d495c Mon Sep 17 00:00:00 2001 From: Petri Virkkunen Date: Wed, 18 Sep 2024 10:51:08 +0300 Subject: [PATCH] Android: Add destruction guard in QAndroidPlatformWindow To avoid calling functions in QAndroidPlatformWindow during/after destruction of the object, create a mutex and use lock_guard to synchronize the destruction of the object and native function calls originating from Android events. Task-number: QTBUG-118231 Change-Id: I29818386456c6969ca507d74574b722bf8a19019 Reviewed-by: Assam Boudjelthia (cherry picked from commit 0f20feea2112c2391e274dc4e81aa38a738b7023) Reviewed-by: Qt Cherry-pick Bot --- .../platforms/android/qandroidplatformwindow.cpp | 16 ++++++++++++++++ .../platforms/android/qandroidplatformwindow.h | 3 +++ 2 files changed, 19 insertions(+) diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp index 4c76bfb3d48..1362b7d3929 100644 --- a/src/plugins/platforms/android/qandroidplatformwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp @@ -96,6 +96,7 @@ void QAndroidPlatformWindow::initialize() QAndroidPlatformWindow::~QAndroidPlatformWindow() { + const auto guard = destructionGuard(); if (window()->isTopLevel()) platformScreen()->removeWindow(this); } @@ -353,6 +354,9 @@ void QAndroidPlatformWindow::setSurface(JNIEnv *env, jobject object, jint window continue; QAndroidPlatformWindow *platformWindow = static_cast(window->handle()); + const auto guard = platformWindow->destructionGuard(); + if (!platformWindow->m_surfaceCreated) + continue; if (platformWindow->nativeViewId() == windowId) platformWindow->onSurfaceChanged(surface); } @@ -373,6 +377,18 @@ void QAndroidPlatformWindow::windowFocusChanged(JNIEnv *env, jobject object, } } +/* + Due to calls originating from Android, it is possible for native methods to + try to manipulate any given instance of QAndroidPlatformWindow when it is + already being destroyed. So we use this to guard against that. It is called + in the destructor, and should also be called in any function registered to + be called from java that may touch an instance of QAndroidPlatformWindow. + */ +QMutexLocker QAndroidPlatformWindow::destructionGuard() +{ + return QMutexLocker(&m_destructionMutex); +} + bool QAndroidPlatformWindow::registerNatives(QJniEnvironment &env) { if (!env.registerNativeMethods(QtJniTypes::Traits::className(), diff --git a/src/plugins/platforms/android/qandroidplatformwindow.h b/src/plugins/platforms/android/qandroidplatformwindow.h index d3822e2d96e..ef4e799a75e 100644 --- a/src/plugins/platforms/android/qandroidplatformwindow.h +++ b/src/plugins/platforms/android/qandroidplatformwindow.h @@ -96,12 +96,15 @@ protected: QWaitCondition m_surfaceWaitCondition; bool m_surfaceCreated = false; QMutex m_surfaceMutex; + QMutex m_destructionMutex; private: static void setSurface(JNIEnv *env, jobject obj, jint windowId, QtJniTypes::Surface surface); Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(setSurface) static void windowFocusChanged(JNIEnv *env, jobject object, jboolean focus, jint windowId); Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(windowFocusChanged) + + [[nodiscard]] QMutexLocker destructionGuard(); }; QT_END_NAMESPACE