summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/thread
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2018-03-05 19:53:37 -0800
committerAapo Keskimolo <aapo.keskimolo@qt.io>2018-03-19 20:36:51 +0000
commit081c001deb75fa38385d3ff8cbbdb4f788529133 (patch)
tree5e718714167d4f75ca6e8a5f50f0ea5afa1002b7 /tests/auto/corelib/thread
parent9fa2626ef8760fe2923af5b47d027e63d9333776 (diff)
QSemaphore: fix deadlock when the woken up thread wakes up another
When the thread that got woken up by release() is supposed to release() to wake up another thread, we were deadlocking. This happened because we cleared the bit indicating that there was contention when the first release(). Instead of storing a single bit, we now store the number of threads waiting. Task-number: QTBUG-66875 Change-Id: I72f5230ad59948f784eafffd15193873502ecba4 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'tests/auto/corelib/thread')
-rw-r--r--tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp69
1 files changed, 69 insertions, 0 deletions
diff --git a/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp b/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp
index a67ecc2471..b7134d0454 100644
--- a/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp
+++ b/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp
@@ -37,6 +37,8 @@ class tst_QSemaphore : public QObject
Q_OBJECT
private slots:
void acquire();
+ void multiRelease();
+ void multiAcquireRelease();
void tryAcquire();
void tryAcquireWithTimeout_data();
void tryAcquireWithTimeout();
@@ -149,6 +151,73 @@ void tst_QSemaphore::acquire()
QCOMPARE(semaphore.available(), 0);
}
+void tst_QSemaphore::multiRelease()
+{
+ class Thread : public QThread
+ {
+ public:
+ QSemaphore &sem;
+ Thread(QSemaphore &sem) : sem(sem) {}
+
+ void run() override
+ {
+ sem.acquire();
+ }
+ };
+
+ QSemaphore sem;
+ QVector<Thread *> threads;
+ threads.resize(4);
+
+ for (Thread *&t : threads)
+ t = new Thread(sem);
+ for (Thread *&t : threads)
+ t->start();
+
+ // wait for all threads to reach the sem.acquire() and then
+ // release them all
+ QTest::qSleep(1);
+ sem.release(threads.size());
+
+ for (Thread *&t : threads)
+ t->wait();
+ qDeleteAll(threads);
+}
+
+void tst_QSemaphore::multiAcquireRelease()
+{
+ class Thread : public QThread
+ {
+ public:
+ QSemaphore &sem;
+ Thread(QSemaphore &sem) : sem(sem) {}
+
+ void run() override
+ {
+ sem.acquire();
+ sem.release();
+ }
+ };
+
+ QSemaphore sem;
+ QVector<Thread *> threads;
+ threads.resize(4);
+
+ for (Thread *&t : threads)
+ t = new Thread(sem);
+ for (Thread *&t : threads)
+ t->start();
+
+ // wait for all threads to reach the sem.acquire() and then
+ // release them all
+ QTest::qSleep(1);
+ sem.release();
+
+ for (Thread *&t : threads)
+ t->wait();
+ qDeleteAll(threads);
+}
+
void tst_QSemaphore::tryAcquire()
{
QSemaphore semaphore;