Android: Fix hang in runOnAndroidThreadSync and requestPermissionsSync

Keep spinning the main event loop if we can't acquire the semaphore,
this way the Android UI thread can post events on it.

Fixes: QTBUG-74076
Change-Id: Ia87e0535f94c67728176918ab928ff5ce8b00f8e
Reviewed-by: VaL Doroshchuk <valentyn.doroshchuk@qt.io>
This commit is contained in:
BogDan Vatra 2019-04-16 17:12:21 +03:00 committed by BogDan Vatra
parent 1269f9cd16
commit 9ca81260e9

View File

@ -45,6 +45,7 @@
#include "qsharedpointer.h" #include "qsharedpointer.h"
#include "qvector.h" #include "qvector.h"
#include "qthread.h" #include "qthread.h"
#include "qcoreapplication.h"
#include <QtCore/qrunnable.h> #include <QtCore/qrunnable.h>
#include <deque> #include <deque>
@ -474,6 +475,17 @@ void QtAndroidPrivate::runOnAndroidThread(const QtAndroidPrivate::Runnable &runn
env->CallStaticVoidMethod(g_jNativeClass, g_runPendingCppRunnablesMethodID); env->CallStaticVoidMethod(g_jNativeClass, g_runPendingCppRunnablesMethodID);
} }
static bool waitForSemaphore(int timeoutMs, QSharedPointer<QSemaphore> sem)
{
while (timeoutMs > 0) {
if (sem->tryAcquire(1, 10))
return true;
timeoutMs -= 10;
QCoreApplication::processEvents();
}
return false;
}
void QtAndroidPrivate::runOnAndroidThreadSync(const QtAndroidPrivate::Runnable &runnable, JNIEnv *env, int timeoutMs) void QtAndroidPrivate::runOnAndroidThreadSync(const QtAndroidPrivate::Runnable &runnable, JNIEnv *env, int timeoutMs)
{ {
QSharedPointer<QSemaphore> sem(new QSemaphore); QSharedPointer<QSemaphore> sem(new QSemaphore);
@ -481,7 +493,7 @@ void QtAndroidPrivate::runOnAndroidThreadSync(const QtAndroidPrivate::Runnable &
runnable(); runnable();
sem->release(); sem->release();
}, env); }, env);
sem->tryAcquire(1, timeoutMs); waitForSemaphore(timeoutMs, sem);
} }
void QtAndroidPrivate::requestPermissions(JNIEnv *env, const QStringList &permissions, const QtAndroidPrivate::PermissionsResultFunc &callbackFunc, bool directCall) void QtAndroidPrivate::requestPermissions(JNIEnv *env, const QStringList &permissions, const QtAndroidPrivate::PermissionsResultFunc &callbackFunc, bool directCall)
@ -524,7 +536,7 @@ QtAndroidPrivate::PermissionsHash QtAndroidPrivate::requestPermissionsSync(JNIEn
*res = result; *res = result;
sem->release(); sem->release();
}, true); }, true);
if (sem->tryAcquire(1, timeoutMs)) if (waitForSemaphore(timeoutMs, sem))
return std::move(*res); return std::move(*res);
else // mustn't touch *res else // mustn't touch *res
return QHash<QString, QtAndroidPrivate::PermissionsResult>(); return QHash<QString, QtAndroidPrivate::PermissionsResult>();