summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@digia.com>2014-03-04 16:17:09 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-11 10:59:16 +0100
commit2d2dbd3199a10985c713e97d32688e001e4cb226 (patch)
tree62e1e34a4507d218ce58f9659c17e73bc9e5ca80
parent54ba9be8850dc7fbeb7151ed5579a22965851008 (diff)
downloadqtconnectivity-2d2dbd3199a10985c713e97d32688e001e4cb226.tar.gz
Android: Fix crashes due to concurrency issues
BroadcastReceiver.onReceive() is executed in the main thread whereas the Qt classes are in a different thread. This created issues whereby Java's qtObject pointer was reset by the Qt classes/thread but onReceive still trying to access the same object later on. In most cases the Qt classes using BroadcastReceiver were half way through their object tear down. This patch fixes the problem by guarding qtObject against concurrent thread access and ensures that the qtObject pointer is reset before the object tear down starts. Change-Id: Iab97b0af8e10686d97419ac8504f2fe69e9536f3 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java15
-rw-r--r--src/bluetooth/android/androidbroadcastreceiver.cpp6
-rw-r--r--src/bluetooth/android/androidbroadcastreceiver_p.h2
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp5
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_android.cpp1
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_android.cpp14
6 files changed, 33 insertions, 10 deletions
diff --git a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java
index 1f0049ef..ba96c0cf 100644
--- a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java
+++ b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java
@@ -62,7 +62,20 @@ public class QtBluetoothBroadcastReceiver extends BroadcastReceiver
public void onReceive(Context context, Intent intent)
{
- jniOnReceive(qtObject, context, intent);
+ synchronized (qtactivity) {
+ if (qtObject == 0)
+ return;
+
+ jniOnReceive(qtObject, context, intent);
+ }
+ }
+
+ public void unregisterReceiver()
+ {
+ synchronized (qtactivity) {
+ qtObject = 0;
+ qtactivity.unregisterReceiver(this);
+ }
}
public native void jniOnReceive(long qtObject, Context context, Intent intent);
diff --git a/src/bluetooth/android/androidbroadcastreceiver.cpp b/src/bluetooth/android/androidbroadcastreceiver.cpp
index c07f7b81..c17502ba 100644
--- a/src/bluetooth/android/androidbroadcastreceiver.cpp
+++ b/src/bluetooth/android/androidbroadcastreceiver.cpp
@@ -72,7 +72,6 @@ AndroidBroadcastReceiver::AndroidBroadcastReceiver(QObject* parent)
AndroidBroadcastReceiver::~AndroidBroadcastReceiver()
{
- unregisterReceiver();
}
bool AndroidBroadcastReceiver::isValid() const
@@ -85,10 +84,7 @@ void AndroidBroadcastReceiver::unregisterReceiver()
if (!valid)
return;
- activityObject.callObjectMethod(
- "unregisterReceiver",
- "(Landroid/content/BroadcastReceiver;)V",
- broadcastReceiverObject.object<jobject>());
+ broadcastReceiverObject.callMethod<void>("unregisterReceiver");
}
void AndroidBroadcastReceiver::addAction(const QAndroidJniObject &action)
diff --git a/src/bluetooth/android/androidbroadcastreceiver_p.h b/src/bluetooth/android/androidbroadcastreceiver_p.h
index 303e4ae8..58c2b40b 100644
--- a/src/bluetooth/android/androidbroadcastreceiver_p.h
+++ b/src/bluetooth/android/androidbroadcastreceiver_p.h
@@ -60,12 +60,12 @@ public:
void addAction(const QAndroidJniObject &filter);
bool isValid() const;
+ void unregisterReceiver();
protected:
friend void QtBroadcastReceiver_jniOnReceive(JNIEnv *, jobject, jlong, jobject, jobject);
virtual void onReceive(JNIEnv *env, jobject context, jobject intent) = 0;
- void unregisterReceiver();
QAndroidJniObject activityObject;
QAndroidJniObject intentFilterObject;
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
index 320e0fb7..4f8ecdff 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
@@ -70,7 +70,10 @@ QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate()
if (m_active)
stop();
- delete receiver;
+ if (receiver) {
+ receiver->unregisterReceiver();
+ delete receiver;
+ }
}
bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const
diff --git a/src/bluetooth/qbluetoothlocaldevice_android.cpp b/src/bluetooth/qbluetoothlocaldevice_android.cpp
index 4e441bc2..ff36837b 100644
--- a/src/bluetooth/qbluetoothlocaldevice_android.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice_android.cpp
@@ -74,6 +74,7 @@ QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate(
QBluetoothLocalDevicePrivate::~QBluetoothLocalDevicePrivate()
{
+ receiver->unregisterReceiver();
delete receiver;
delete obj;
}
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
index e0e17c14..7b081e04 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
@@ -98,8 +98,14 @@ QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate(
QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate()
{
- delete receiver;
- delete localDeviceReceiver;
+ if (receiver) {
+ receiver->unregisterReceiver();
+ delete receiver;
+ }
+ if (localDeviceReceiver) {
+ localDeviceReceiver->unregisterReceiver();
+ delete localDeviceReceiver;
+ }
}
void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address)
@@ -209,6 +215,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &addr
jboolean result = remoteDevice.callMethod<jboolean>("fetchUuidsWithSdp");
if (!result) {
//kill receiver to limit load of signals
+ receiver->unregisterReceiver();
receiver->deleteLater();
receiver = 0;
qCWarning(QT_BT_ANDROID) << "Cannot start dynamic fetch.";
@@ -223,6 +230,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::stop()
discoveredDevices.clear();
//kill receiver to limit load of signals
+ receiver->unregisterReceiver();
receiver->deleteLater();
receiver = 0;
@@ -493,6 +501,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_fetchUuidsTimeout()
Q_ASSERT(sdpCache.isEmpty());
//kill receiver to limit load of signals
+ receiver->unregisterReceiver();
receiver->deleteLater();
receiver = 0;
_q_serviceDiscoveryFinished();
@@ -509,6 +518,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_hostModeStateChanged(QBluetoothL
errorString = QBluetoothServiceDiscoveryAgent::tr("Device is powered off");
//kill receiver to limit load of signals
+ receiver->unregisterReceiver();
receiver->deleteLater();
receiver = 0;