Details
-
Bug
-
Resolution: Done
-
P1: Critical
-
5.5.0, 5.6
-
None
-
0aedca2f9756fa33420fb6b3f003f364424f9134
Description
Consider the following example:
#include <QThread> #include <QReadWriteLock> #include <QDebug> #include <unistd.h> class RecursiveLock : public QReadWriteLock { public: RecursiveLock() : QReadWriteLock(QReadWriteLock::Recursive) {} }; RecursiveLock lock; class ReadLockThread : public QThread { Q_OBJECT protected: void run() { QReadLocker lock1(&lock); qDebug() << "Read lock 1"; sleep(5); { QReadLocker lock2(&lock); qDebug() << "Read lock 2"; } } }; int main(int argc, char *argv[]) { ReadLockThread t; t.start(); sleep(2); QWriteLocker lock3(&lock); qDebug() << "Write lock"; } #include "main.moc"
This should (in most cases)
1. start the thread
2. acquire lock1
3. start waiting on lock3 in the main thread
4. acquire lock2 recursively
5. stop the thread, releasing lock1 and lock2
6. acquire lock3
7. quit
Actually it deadlocks at step 4, though. This seems to be a regression from 5.4 to 5.5.
Backtraces of both threads during the deadlock:
Thread 2 (Thread 0x7f8939d18700 (LWP 4630)): #0 pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:185 No locals. #1 0x00007f893d9767fb in QWaitCondition::wait(QMutex*, unsigned long) () from /home/ulf/Qt/5.5/gcc_64/lib/libQt5Core.so.5 No symbol table info available. #2 0x00007f893d96ec4c in QReadWriteLock::lockForRead() () from /home/ulf/Qt/5.5/gcc_64/lib/libQt5Core.so.5 No symbol table info available. #3 0x00000000004018bb in QReadLocker::relock (this=0x7f8939d17e30) at ../../Qt/5.5/gcc_64/include/QtCore/qreadwritelock.h:98 No locals. #4 0x0000000000401942 in QReadLocker::QReadLocker (this=0x7f8939d17e30, areadWriteLock=0x602ca8 <lock>) at ../../Qt/5.5/gcc_64/include/QtCore/qreadwritelock.h:117 No locals. #5 0x0000000000401be5 in ReadLockThread::run (this=0x7ffc31e8f2e0) at ../deadlock/main.cpp:58 lock2 = {q_val = 6302888} lock1 = {q_val = 6302889} __PRETTY_FUNCTION__ = "virtual void ReadLockThread::run()" #6 0x00007f893d9757df in ?? () from /home/ulf/Qt/5.5/gcc_64/lib/libQt5Core.so.5 No symbol table info available. #7 0x00007f893d6bd0a4 in start_thread (arg=0x7f8939d18700) at pthread_create.c:309 __res = <optimized out> pd = 0x7f8939d18700 now = <optimized out> unwind_buf = {cancel_jmp_buf = {{jmp_buf = {140227357280000, 7339065152721156614, 1, 140227429761120, 7, 140227357280000, -7292476246588098042, -7292486643519423994}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}} not_first_call = <optimized out> pagesize_m1 = <optimized out> sp = <optimized out> freesize = <optimized out> __PRETTY_FUNCTION__ = "start_thread" #8 0x00007f893cbd004d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111 No locals. Thread 1 (Thread 0x7f893e206740 (LWP 4622)): #0 pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:185 No locals. #1 0x00007f893d9767fb in QWaitCondition::wait(QMutex*, unsigned long) () from /home/ulf/Qt/5.5/gcc_64/lib/libQt5Core.so.5 No symbol table info available. #2 0x00007f893d96ee46 in QReadWriteLock::lockForWrite() () from /home/ulf/Qt/5.5/gcc_64/lib/libQt5Core.so.5 No symbol table info available. #3 0x00000000004019eb in QWriteLocker::relock (this=0x7ffc31e8f2d0) at ../../Qt/5.5/gcc_64/include/QtCore/qreadwritelock.h:142 No locals. #4 0x0000000000401a72 in QWriteLocker::QWriteLocker (this=0x7ffc31e8f2d0, areadWriteLock=0x602ca8 <lock>) at ../../Qt/5.5/gcc_64/include/QtCore/qreadwritelock.h:162 No locals. #5 0x00000000004014c3 in main (argc=1, argv=0x7ffc31e8f418) at ../deadlock/main.cpp:69 t = {<QThread> = {<No data fields>}, static staticMetaObject = {d = {superdata = 0x7f893e00e2c0 <QThread::staticMetaObject>, stringdata = 0x401fc0 <qt_meta_stringdata_ReadLockThread>, data = 0x402000 <qt_meta_data_ReadLockThread>, static_metacall = 0x401576 <ReadLockThread::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)>, relatedMetaObjects = 0x0, extradata = 0x0}}} lock3 = {q_val = 6302888} __PRETTY_FUNCTION__ = "int main(int, char**)"