Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Mysterious QMutex destroying locked mutex
QtWS25 Last Chance

Mysterious QMutex destroying locked mutex

Scheduled Pinned Locked Moved Unsolved General and Desktop
qthreadqmutexcrashwindows7
14 Posts 4 Posters 4.2k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • MasterBLBM Offline
    MasterBLBM Offline
    MasterBLB
    wrote on last edited by
    #1

    Hi mates

    I got that warning (and application crash) for the following code:

        for (const QString &video : videoFiles)
        {
            ThumbnailExtractor *extractor = new ThumbnailExtractor(counter, folderPath + '/' + video);
            QThread *thread = new QThread();
            extractor->moveToThread(thread);        
    
            connect(thread, SIGNAL(started()), extractor, SLOT(generateThumbnail()), Qt::QueuedConnection);
            connect(extractor, SIGNAL(finished()), thread, SLOT(quit()), Qt::QueuedConnection);
    
            //automatically delete thread and thumbnail extractor object when work is done
            connect(extractor, SIGNAL(finished()), extractor, SLOT(deleteLater()));
            connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    
            thread->start();
     }
    

    ThumbnailExtractor is not using QMutex at all, the crashing one comes from QThread. What I've messed up?

    KroMignonK kshegunovK 2 Replies Last reply
    0
    • MasterBLBM MasterBLB

      Hi mates

      I got that warning (and application crash) for the following code:

          for (const QString &video : videoFiles)
          {
              ThumbnailExtractor *extractor = new ThumbnailExtractor(counter, folderPath + '/' + video);
              QThread *thread = new QThread();
              extractor->moveToThread(thread);        
      
              connect(thread, SIGNAL(started()), extractor, SLOT(generateThumbnail()), Qt::QueuedConnection);
              connect(extractor, SIGNAL(finished()), thread, SLOT(quit()), Qt::QueuedConnection);
      
              //automatically delete thread and thumbnail extractor object when work is done
              connect(extractor, SIGNAL(finished()), extractor, SLOT(deleteLater()));
              connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
      
              thread->start();
       }
      

      ThumbnailExtractor is not using QMutex at all, the crashing one comes from QThread. What I've messed up?

      KroMignonK Offline
      KroMignonK Offline
      KroMignon
      wrote on last edited by KroMignon
      #2

      @MasterBLB said in Mysterious QMutex destroying locked mutex:

      ThumbnailExtractor is not using QMutex at all, the crashing one comes from QThread. What I've messed up?

      I seems to me that ThumbnailExtractor have QObject based members which are created in constructor but which stays in current thread.

      Are you sure all QObject base members for this class are created in generateThumbnail() or have the class instance as parent?

      It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

      1 Reply Last reply
      0
      • MasterBLBM Offline
        MasterBLBM Offline
        MasterBLB
        wrote on last edited by
        #3

        Indeed it has:

        class ThumbnailExtractor : public QObject
        {
            Q_OBJECT
        ....
        private:
            QMediaPlayer *player;
            ThumbailVideoSurface *surface;
            QMediaContent content;//that's not a descendant of QObject
        .....
        };
        

        however, in the constructor I have:

        ThumbnailExtractor::ThumbnailExtractor(int counter, const QString &videoFilePath, QObject *parent)
        : QObject(parent), content(videoFilePath)
        {    
            player = new QMediaPlayer(this);
            surface = new ThumbailVideoSurface(counter, this);
            player->setVideoOutput(surface);
            connect(surface, SIGNAL(stopMedia()), player, SLOT(stop()), Qt::QueuedConnection);
            connect(surface, SIGNAL(stopMedia()), this, SIGNAL(finished()), Qt::QueuedConnection);
        
            player->setMuted(true);
        
            connect(player, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(error(QMediaPlayer::Error)));//, Qt::QueuedConnection);
            connect(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(mediaStatusChanged(QMediaPlayer::MediaStatus)));//, Qt::QueuedConnection);
        }
        

        so yeah, these should be moved to another thread along with ThumbnailExtractor object.

        KroMignonK 1 Reply Last reply
        0
        • MasterBLBM MasterBLB

          Indeed it has:

          class ThumbnailExtractor : public QObject
          {
              Q_OBJECT
          ....
          private:
              QMediaPlayer *player;
              ThumbailVideoSurface *surface;
              QMediaContent content;//that's not a descendant of QObject
          .....
          };
          

          however, in the constructor I have:

          ThumbnailExtractor::ThumbnailExtractor(int counter, const QString &videoFilePath, QObject *parent)
          : QObject(parent), content(videoFilePath)
          {    
              player = new QMediaPlayer(this);
              surface = new ThumbailVideoSurface(counter, this);
              player->setVideoOutput(surface);
              connect(surface, SIGNAL(stopMedia()), player, SLOT(stop()), Qt::QueuedConnection);
              connect(surface, SIGNAL(stopMedia()), this, SIGNAL(finished()), Qt::QueuedConnection);
          
              player->setMuted(true);
          
              connect(player, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(error(QMediaPlayer::Error)));//, Qt::QueuedConnection);
              connect(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(mediaStatusChanged(QMediaPlayer::MediaStatus)));//, Qt::QueuedConnection);
          }
          

          so yeah, these should be moved to another thread along with ThumbnailExtractor object.

          KroMignonK Offline
          KroMignonK Offline
          KroMignon
          wrote on last edited by
          #4

          @MasterBLB said in Mysterious QMutex destroying locked mutex:

          so yeah, these should be moved to another thread along with ThumbnailExtractor object.

          What about ThumbailVideoSurface ?

          It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

          MasterBLBM 1 Reply Last reply
          0
          • KroMignonK KroMignon

            @MasterBLB said in Mysterious QMutex destroying locked mutex:

            so yeah, these should be moved to another thread along with ThumbnailExtractor object.

            What about ThumbailVideoSurface ?

            MasterBLBM Offline
            MasterBLBM Offline
            MasterBLB
            wrote on last edited by MasterBLB
            #5

            @KroMignon said in Mysterious QMutex destroying locked mutex:

            @MasterBLB said in Mysterious QMutex destroying locked mutex:

            so yeah, these should be moved to another thread along with ThumbnailExtractor object.

            What about ThumbailVideoSurface ?

            It does not contain any member variables.
            EDIT:
            Wrong! It has just one int member; I meant it does not contain any QObject-related members.

            KroMignonK VRoninV 2 Replies Last reply
            0
            • MasterBLBM MasterBLB

              @KroMignon said in Mysterious QMutex destroying locked mutex:

              @MasterBLB said in Mysterious QMutex destroying locked mutex:

              so yeah, these should be moved to another thread along with ThumbnailExtractor object.

              What about ThumbailVideoSurface ?

              It does not contain any member variables.
              EDIT:
              Wrong! It has just one int member; I meant it does not contain any QObject-related members.

              KroMignonK Offline
              KroMignonK Offline
              KroMignon
              wrote on last edited by KroMignon
              #6

              @MasterBLB I had troubles with QSoundEffect and thread changes.

              I don't know if QMediaPlayer does not have same kind of problems.

              My suggestion would be to create QMediaPlayer instance when runnin in right thread.

              It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

              1 Reply Last reply
              1
              • MasterBLBM MasterBLB

                @KroMignon said in Mysterious QMutex destroying locked mutex:

                @MasterBLB said in Mysterious QMutex destroying locked mutex:

                so yeah, these should be moved to another thread along with ThumbnailExtractor object.

                What about ThumbailVideoSurface ?

                It does not contain any member variables.
                EDIT:
                Wrong! It has just one int member; I meant it does not contain any QObject-related members.

                VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by
                #7

                @MasterBLB said in Mysterious QMutex destroying locked mutex:

                it does not contain any QObject-related members.

                Given the name, are you by any chance using QPixmap in it?

                From https://doc.qt.io/qt-5/thread-basics.html#gui-thread-and-worker-thread

                All widgets and several related classes, for example QPixmap, don't work in secondary threads.

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                1 Reply Last reply
                0
                • MasterBLBM Offline
                  MasterBLBM Offline
                  MasterBLB
                  wrote on last edited by MasterBLB
                  #8

                  I'm using QImage:

                  bool ThumbailVideoSurface::present(const QVideoFrame &frame)
                  {
                      if (frame.isValid())
                      {
                          QImage thumbnail(frame.image());
                          thumbnail.save("thumbnail" + QString::number(tempCounter) + ".png");//that's only temporary, finally I'm going to create some kind of QMap <fileName, thumbnail QPixmap/QImage>
                  
                          //stop();//to wykrzacza aplikacjÄ™
                          emit stopMedia();
                      }
                  
                      return true;
                  }
                  

                  but I was going to switch to QPixmap later on, for rescaling the image.

                  1 Reply Last reply
                  0
                  • MasterBLBM Offline
                    MasterBLBM Offline
                    MasterBLB
                    wrote on last edited by
                    #9

                    Moving creation of QMediaPlayer in the new QThread didn't helped as well.

                    1 Reply Last reply
                    0
                    • MasterBLBM MasterBLB

                      Hi mates

                      I got that warning (and application crash) for the following code:

                          for (const QString &video : videoFiles)
                          {
                              ThumbnailExtractor *extractor = new ThumbnailExtractor(counter, folderPath + '/' + video);
                              QThread *thread = new QThread();
                              extractor->moveToThread(thread);        
                      
                              connect(thread, SIGNAL(started()), extractor, SLOT(generateThumbnail()), Qt::QueuedConnection);
                              connect(extractor, SIGNAL(finished()), thread, SLOT(quit()), Qt::QueuedConnection);
                      
                              //automatically delete thread and thumbnail extractor object when work is done
                              connect(extractor, SIGNAL(finished()), extractor, SLOT(deleteLater()));
                              connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
                      
                              thread->start();
                       }
                      

                      ThumbnailExtractor is not using QMutex at all, the crashing one comes from QThread. What I've messed up?

                      kshegunovK Offline
                      kshegunovK Offline
                      kshegunov
                      Moderators
                      wrote on last edited by
                      #10

                      @MasterBLB said in Mysterious QMutex destroying locked mutex:

                      ThumbnailExtractor is not using QMutex at all, the crashing one comes from QThread. What I've messed up?

                      You don't wait for the thread to finish from what I can tell. Also when diagnosing crashes, please provide a stack trace.

                      Read and abide by the Qt Code of Conduct

                      1 Reply Last reply
                      1
                      • MasterBLBM Offline
                        MasterBLBM Offline
                        MasterBLB
                        wrote on last edited by
                        #11

                        A try to check stack frame was the 1st I've tried before writing the post, sadly there is none. Besides, pls explain me how I don't wait for the thread to stop before deleting if I have the lines:

                        connect(extractor, SIGNAL(finished()), thread, SLOT(quit()), Qt::QueuedConnection);
                        connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
                        
                        kshegunovK 1 Reply Last reply
                        0
                        • MasterBLBM MasterBLB

                          A try to check stack frame was the 1st I've tried before writing the post, sadly there is none. Besides, pls explain me how I don't wait for the thread to stop before deleting if I have the lines:

                          connect(extractor, SIGNAL(finished()), thread, SLOT(quit()), Qt::QueuedConnection);
                          connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
                          
                          kshegunovK Offline
                          kshegunovK Offline
                          kshegunov
                          Moderators
                          wrote on last edited by
                          #12

                          @MasterBLB said in Mysterious QMutex destroying locked mutex:

                          A try to check stack frame was the 1st I've tried before writing the post, sadly there is none.

                          If you don't have a stack trace, then the program is not running. There's no crash without a stack is the point. If you simply get a warning from the Qt runtime, then run your program in the debuger with the environment variable QT_FATAL_WARNINGS set to 1 so it trips at the point of the actual error and then extract the stack trace.

                          Besides, pls explain me how I don't wait for the thread to stop before deleting if I have the lines:

                          QThread::wait (equivalent to std::thread::join) comes to mind. The fact that a signal was raised doesn't mean that the thread (which is simply a 'special' function) has finished executing.

                          Read and abide by the Qt Code of Conduct

                          1 Reply Last reply
                          1
                          • MasterBLBM Offline
                            MasterBLBM Offline
                            MasterBLB
                            wrote on last edited by
                            #13

                            @kshegunov said in Mysterious QMutex destroying locked mutex:

                            If you don't have a stack trace, then the program is not running. There's no crash without a stack is the point. If you simply get a warning from the Qt runtime, then run your program in the debuger with the environment variable QT_FATAL_WARNINGS set to 1 so it trips at the point of the actual error and then extract the stack trace.

                            I mean there is no readable/useful stack frame, neither I don't know which of over 100 threads listed in debugger is the one I should check.

                            I tried that QT_FATAL_WARNINGS before, sadly due to some crap with QML ("QML QQuickText: Detected anchors on an item that is managed by a layout. This is undefined behavior; use Layout.alignment instead.") I won't even reach the code part which contains threads.

                            kshegunovK 1 Reply Last reply
                            0
                            • MasterBLBM MasterBLB

                              @kshegunov said in Mysterious QMutex destroying locked mutex:

                              If you don't have a stack trace, then the program is not running. There's no crash without a stack is the point. If you simply get a warning from the Qt runtime, then run your program in the debuger with the environment variable QT_FATAL_WARNINGS set to 1 so it trips at the point of the actual error and then extract the stack trace.

                              I mean there is no readable/useful stack frame, neither I don't know which of over 100 threads listed in debugger is the one I should check.

                              I tried that QT_FATAL_WARNINGS before, sadly due to some crap with QML ("QML QQuickText: Detected anchors on an item that is managed by a layout. This is undefined behavior; use Layout.alignment instead.") I won't even reach the code part which contains threads.

                              kshegunovK Offline
                              kshegunovK Offline
                              kshegunov
                              Moderators
                              wrote on last edited by kshegunov
                              #14

                              Humor me, will you?

                              constexpr int poolSize = 16;
                              QVector<QThread *> threadPool(poolSize);
                              
                              QCoreApplication * app = QCoreApplication::instance();
                              for (size_t i = 0; i < poolSize; i++)  {
                                  QThread * thread = new QThread(app);
                                  thread->start();
                              
                                  QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater);
                              }
                              QObject::connect(app, &QCoreApplication::aboutToQuit, [threadPool] () -> void {
                                  for (QThread * thread : threadPool)  {
                                      thread->quit();
                                      thread->wait();
                                  }
                              });
                              
                              int index = 0;
                              for (const QString &video : videoFiles)
                              {
                                  ThumbnailExtractor *extractor = new ThumbnailExtractor(counter, folderPath + '/' + video);
                                  extractor->moveToThread(threadPool[index++ % poolSize]);
                              
                                  QObject::connect(extractor, &ThumbnailExtractor::finished, extractor, &QObject::deleteLater);
                                  QMetaObject::invokeMethod(extractor, &ThumbnailExtractor::generateThumbnail, Qt::QueuedConnection);
                              }
                              

                              A note here:
                              QMediaPlayer and related classes don't seem to be reentrant so you can't use them from different threads. Stick to the main one.

                              Read and abide by the Qt Code of Conduct

                              1 Reply Last reply
                              0

                              • Login

                              • Login or register to search.
                              • First post
                                Last post
                              0
                              • Categories
                              • Recent
                              • Tags
                              • Popular
                              • Users
                              • Groups
                              • Search
                              • Get Qt Extensions
                              • Unsolved