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
Pick-to: 6.8
Change-Id: I29818386456c6969ca507d74574b722bf8a19019
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
This commit is contained in:
Petri Virkkunen 2024-09-18 10:51:08 +03:00
parent 9343d1ab6e
commit 0f20feea21
2 changed files with 19 additions and 0 deletions

View File

@ -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<QAndroidPlatformWindow *>(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<QMutex> QAndroidPlatformWindow::destructionGuard()
{
return QMutexLocker(&m_destructionMutex);
}
bool QAndroidPlatformWindow::registerNatives(QJniEnvironment &env)
{
if (!env.registerNativeMethods(QtJniTypes::Traits<QtJniTypes::QtWindow>::className(),

View File

@ -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<QMutex> destructionGuard();
};
QT_END_NAMESPACE