diff options
author | Bartlomiej Moskal <bartlomiej.moskal@qt.io> | 2023-02-24 08:34:37 +0100 |
---|---|---|
committer | Bartlomiej Moskal <bartlomiej.moskal@qt.io> | 2023-03-03 09:31:53 +0000 |
commit | 26c2569b73d884e3130705c77b8f2920f5645029 (patch) | |
tree | 1aafd32079dab5d471ca23a0461ec271ab103096 | |
parent | 91a14c6af43f2282d4378ff17fcd9f41ca539ac0 (diff) |
Android: Fix for possible thread deadlock
QtAndroidWebViewController constructor blocks a qGuiThread until
the WebView is created and configured in UI thread. Such an
implementation can easily lead to the deadlock (For example in the case
of handling InputConnection - it is exactly the opposite. UI thread is
blocked and waits for handling event by qGuiThread). That's why we need
to lock AndroidDeadlockProtector before blocking qGuiThread.
This implementation resolves potential deadlock using
AndroidDeadlockProtector. If protector cannot by locked, qGuiThread will
handle events to make it possible.
Fixes: QTBUG-82810
Pick-to: 6.5 6.4 6.2 5.15
Change-Id: I71aaea9ceb7c41b818ed533ce41c70b5c0e8d7de
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
-rw-r--r-- | src/plugins/android/qandroidwebview.cpp | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/src/plugins/android/qandroidwebview.cpp b/src/plugins/android/qandroidwebview.cpp index 5e13c08..57f0864 100644 --- a/src/plugins/android/qandroidwebview.cpp +++ b/src/plugins/android/qandroidwebview.cpp @@ -15,6 +15,9 @@ #include <QtCore/qurl.h> #include <QtCore/qdebug.h> +#include <QAbstractEventDispatcher> +#include <QThread> + QT_BEGIN_NAMESPACE QAndroidWebViewSettingsPrivate::QAndroidWebViewSettingsPrivate(QJniObject viewController, QObject *p) @@ -92,10 +95,22 @@ QAndroidWebViewPrivate::QAndroidWebViewPrivate(QObject *p) , m_callbackId(0) , m_window(0) { + // QtAndroidWebViewController constructor blocks a qGuiThread until + // the WebView is created and configured in UI thread. + // That is why we cannot proceed until AndroidDeadlockProtector is locked + while (!QtAndroidPrivate::acquireAndroidDeadlockProtector()) { + auto eventDispatcher = QThread::currentThread()->eventDispatcher(); + if (eventDispatcher) + eventDispatcher->processEvents( + QEventLoop::ExcludeUserInputEvents|QEventLoop::ExcludeSocketNotifiers); + } m_viewController = QJniObject(qtAndroidWebViewControllerClass, "(Landroid/app/Activity;J)V", QtAndroidPrivate::activity(), m_id); + + QtAndroidPrivate::releaseAndroidDeadlockProtector(); + m_webView = m_viewController.callObjectMethod("getWebView", "()Landroid/webkit/WebView;"); m_settings = new QAndroidWebViewSettingsPrivate(m_viewController, this); |