summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Olav Tvete <paul.tvete@digia.com>2014-09-03 09:57:58 +0200
committerPaul Olav Tvete <paul.tvete@digia.com>2014-09-03 15:18:49 +0200
commit7e1e42cbf269c4fd5bbfa0411964bd14e5ae549c (patch)
treea483883d57ecfeaf1c636bd9a566670e70d338ee /src
parenta02d798bbde691b8dd8f9c95aa54c9702cbad59a (diff)
Android: Avoid deadlocks on suspend
Get rid of the rendezvous at shutdown: the android thread does not need to wait for the GUI thread. Since the GUI thread frequently does blocking calls to the android thread, this fixes several known and potential deadlocks. Task-number: QTBUG-41072 Change-Id: Ia6fa8da026b1727e7352b22f4df4d72b63b8c847 Reviewed-by: BogDan Vatra <bogdan@kde.org> Reviewed-by: Christian Stromme <christian.stromme@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/android/qandroideventdispatcher.cpp21
-rw-r--r--src/plugins/platforms/android/qandroideventdispatcher.h2
2 files changed, 14 insertions, 9 deletions
diff --git a/src/plugins/platforms/android/qandroideventdispatcher.cpp b/src/plugins/platforms/android/qandroideventdispatcher.cpp
index 074ba71f80..ab5070af9d 100644
--- a/src/plugins/platforms/android/qandroideventdispatcher.cpp
+++ b/src/plugins/platforms/android/qandroideventdispatcher.cpp
@@ -55,20 +55,26 @@ QAndroidEventDispatcher::~QAndroidEventDispatcher()
QAndroidEventDispatcherStopper::instance()->removeEventDispatcher(this);
}
+enum States {Running = 0, StopRequest = 1, Stopping = 2};
+
void QAndroidEventDispatcher::start()
{
- if (m_stopRequest.testAndSetAcquire(1, 0)) {
- m_dispatcherSemaphore.release();
+ int prevState = m_stopRequest.fetchAndStoreAcquire(Running);
+ if (prevState == Stopping) {
+ m_semaphore.release();
wakeUp();
+ } else if (prevState == Running) {
+ qWarning("Error: start without corresponding stop");
}
+ //else if prevState == StopRequest, no action needed
}
void QAndroidEventDispatcher::stop()
{
- if (m_stopRequest.testAndSetAcquire(0, 1)) {
+ if (m_stopRequest.testAndSetAcquire(Running, StopRequest))
wakeUp();
- m_stopperSemaphore.acquire();
- }
+ else
+ qWarning("Error: start/stop out of sync");
}
void QAndroidEventDispatcher::goingToStop(bool stop)
@@ -80,9 +86,8 @@ void QAndroidEventDispatcher::goingToStop(bool stop)
int QAndroidEventDispatcher::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timespec *timeout)
{
- if (m_stopRequest.load() == 1) {
- m_stopperSemaphore.release();
- m_dispatcherSemaphore.acquire();
+ if (m_stopRequest.testAndSetAcquire(StopRequest, Stopping)) {
+ m_semaphore.acquire();
wakeUp();
}
diff --git a/src/plugins/platforms/android/qandroideventdispatcher.h b/src/plugins/platforms/android/qandroideventdispatcher.h
index 8d1bcf2122..284c5fd392 100644
--- a/src/plugins/platforms/android/qandroideventdispatcher.h
+++ b/src/plugins/platforms/android/qandroideventdispatcher.h
@@ -66,7 +66,7 @@ protected:
private:
QAtomicInt m_stopRequest;
QAtomicInt m_goingToStop;
- QSemaphore m_dispatcherSemaphore, m_stopperSemaphore;
+ QSemaphore m_semaphore;
};
class QAndroidEventDispatcherStopper