Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-34460

QThreadPool has a dead lock in destructor if instantiated as global

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P2: Important
    • 5.12.0
    • 5.1.1
    • Core: Threads
    • None
    • Windows 7 x64 VS2010
    • f4394c86b68050c37ef6e56a7c30c50870875bcd

    Description

      minimal_example.cpp
      #include <QThreadPool>
      
      Q_GLOBAL_STATIC(QThreadPool, global_pool)
      
      class SleepRunable : public QRunnable {
      public:
          SleepRunable() {
              setAutoDelete(true);
          }
      
          void run() {
              QThread::msleep(100);
          }
      };
      
      void startTask(QThreadPool* pool) {
          pool->setMaxThreadCount(1);
          pool->start(new SleepRunable());
      }
      
      void good1() {
          QThreadPool pool;
          startTask(&pool);
      }
      
      
      void good2() {
          startTask(global_pool);
          global_pool->waitForDone();
      }
      
      void bad() {
          startTask(global_pool);
          // infinity wait in global_pool->dtor
      }
      
      int main(int argc, char *argv[])
      {
          //good1();
          //good2();
          bad();
      }
      
      qtbase/src/corelib/thread/qthreadpool.cpp:299
      if (msecs < 0) {
              while (!(queue.isEmpty() && activeThreads == 0))
                  noActiveThreads.wait(locker.mutex());
          } else {
      

      activeThreads is one so Thread #0 start waiting, but no threads active.
      And noActiveThreads never fires.

      Seems somebody kills or stops all threads after Thread #0 leaves main().

      Look! QCoreApplication knows about this problem, but solves it partialy

      qtbase/src/corelib/kernel/qcoreapplication.cpp:759
          QThreadPool *globalThreadPool = 0;
          QT_TRY {
              globalThreadPool = QThreadPool::globalInstance();
          } QT_CATCH (...) {
              // swallow the exception, since destructors shouldn't throw
          }
          if (globalThreadPool)
              globalThreadPool->waitForDone();
      

      This behaviour should be fixed or documented.

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              thiago Thiago Macieira
              setosha Anton Sergunov
              Votes:
              3 Vote for this issue
              Watchers:
              7 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes