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. Deadlocked QMessageBox doesn't appear at signal processing
Forum Updated to NodeBB v4.3 + New Features

Deadlocked QMessageBox doesn't appear at signal processing

Scheduled Pinned Locked Moved Unsolved General and Desktop
13 Posts 4 Posters 1.9k Views 1 Watching
  • 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.
  • M Offline
    M Offline
    mr.indieperson
    wrote on last edited by
    #1

    What i want to do

    I have a main GUI thread executing this:

    void main(int argc, char** argv)
    {
        QApplication app(argc, argv);
        MainWindow mainWindow; // an engine thread is started here
        mainWindow.show();
        app.exec(); // here the GUI thread enters the event processing loop
    }
    

    I connect a signal and a slot to handle notifications in GUI thread (this is MainWindow) with BlockingQueuedConnection type:

    connect(&warningSignalEmitter, SIGNAL(popuped(QString)),
        this, SLOT(onPopupWarning(QString)), Qt::BlockingQueuedConnection);
    

    If a signal is emitted, the GUI thread shows a MessageBox:

    void MainWindow::onPopupWarning(QString message)
    {
        QMessageBox::warning(nullptr, "Warning", message);
    }
    

    I have an engine thread creating OpenGL context and executing a rendering loop. QOpenGLDebugLogger is initialized in this thread with this code:

    logger = new QOpenGLDebugLogger();
    logger->initialize();
    
    connect(logger, SIGNAL(messageLogged(QOpenGLDebugMessage)),
        this, SLOT(glDebugMessageLogged(QOpenGLDebugMessage)),
        Qt::ConnectionType::DirectConnection);
    
    logger->startLogging(QOpenGLDebugLogger::LoggingMode::SynchronousLogging);
    

    The connection type is DirectConnection, so if an error occures when the engine thread calls OpenGL function, the engine thread enters the slot, which is:

    void Engine::glDebugMessageLogged(const QOpenGLDebugMessage &debugMessage)
    {
        emit warningSignalEmitter.popuped(debugMessage.message());
    }
    

    The engine thread is locked here until the GUI thread has exited MainWindow::onPopupWarning.

    So i want see a Message Box if an error has occured in OpenGL function call.

    My problem

    If i just emit a signal with emit warningSignalEmitter.popuped(debugMessage.message()) somewhere in engine code everything works fine, i see a MessageBox, the engine thread is locked at signal emitting, and the GUI thread is locked in onPopupWarning slot until i have clicked OK on the message box.

    While the message box is being showed i see this normal stack trace:

    BUT if an error occures in OpenGL function call, the engine thread successfully enteres glDebugMessageLogged slot (because of direct connection) and does signal emitting. After that it is locked as expected. The GUI thread enteres the onPopupWarning slot, but when it calls QMessageBox::warning, the Message Box doesn't appear, the GUI thread has being locked at this call, and i can't click OK and continue execution.

    And I see this unusual stack trace at this deadlock:

    What may it be?

    kshegunovK 1 Reply Last reply
    0
    • dheerendraD Offline
      dheerendraD Offline
      dheerendra
      Qt Champions 2022
      wrote on last edited by
      #2

      Why do you pass BlockingQueuedConnection to connect ?

      connect(&warningSignalEmitter, SIGNAL(popuped(QString)),
      this, SLOT(onPopupWarning(QString)), Qt::BlockingQueuedConnection);

      Here the signal is sent from engineThread & slot is in gui thread. Since you are passing blocked queued connection, engine thread will hang till slot is complete. Here inside the slot you are calling message box. unless you close message box, slot is not finished.

      Hence you have threads are blocked. Hope it helps.

      Dheerendra
      @Community Service
      Certified Qt Specialist
      http://www.pthinks.com

      M 1 Reply Last reply
      2
      • M mr.indieperson

        What i want to do

        I have a main GUI thread executing this:

        void main(int argc, char** argv)
        {
            QApplication app(argc, argv);
            MainWindow mainWindow; // an engine thread is started here
            mainWindow.show();
            app.exec(); // here the GUI thread enters the event processing loop
        }
        

        I connect a signal and a slot to handle notifications in GUI thread (this is MainWindow) with BlockingQueuedConnection type:

        connect(&warningSignalEmitter, SIGNAL(popuped(QString)),
            this, SLOT(onPopupWarning(QString)), Qt::BlockingQueuedConnection);
        

        If a signal is emitted, the GUI thread shows a MessageBox:

        void MainWindow::onPopupWarning(QString message)
        {
            QMessageBox::warning(nullptr, "Warning", message);
        }
        

        I have an engine thread creating OpenGL context and executing a rendering loop. QOpenGLDebugLogger is initialized in this thread with this code:

        logger = new QOpenGLDebugLogger();
        logger->initialize();
        
        connect(logger, SIGNAL(messageLogged(QOpenGLDebugMessage)),
            this, SLOT(glDebugMessageLogged(QOpenGLDebugMessage)),
            Qt::ConnectionType::DirectConnection);
        
        logger->startLogging(QOpenGLDebugLogger::LoggingMode::SynchronousLogging);
        

        The connection type is DirectConnection, so if an error occures when the engine thread calls OpenGL function, the engine thread enters the slot, which is:

        void Engine::glDebugMessageLogged(const QOpenGLDebugMessage &debugMessage)
        {
            emit warningSignalEmitter.popuped(debugMessage.message());
        }
        

        The engine thread is locked here until the GUI thread has exited MainWindow::onPopupWarning.

        So i want see a Message Box if an error has occured in OpenGL function call.

        My problem

        If i just emit a signal with emit warningSignalEmitter.popuped(debugMessage.message()) somewhere in engine code everything works fine, i see a MessageBox, the engine thread is locked at signal emitting, and the GUI thread is locked in onPopupWarning slot until i have clicked OK on the message box.

        While the message box is being showed i see this normal stack trace:

        BUT if an error occures in OpenGL function call, the engine thread successfully enteres glDebugMessageLogged slot (because of direct connection) and does signal emitting. After that it is locked as expected. The GUI thread enteres the onPopupWarning slot, but when it calls QMessageBox::warning, the Message Box doesn't appear, the GUI thread has being locked at this call, and i can't click OK and continue execution.

        And I see this unusual stack trace at this deadlock:

        What may it be?

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

        Check that the threads on emission and reception are indeed different. The stack you provided is for the GUI thread only, consider extracting the trace for the two threads to see where it locks and why.

        Read and abide by the Qt Code of Conduct

        M 1 Reply Last reply
        0
        • dheerendraD dheerendra

          Why do you pass BlockingQueuedConnection to connect ?

          connect(&warningSignalEmitter, SIGNAL(popuped(QString)),
          this, SLOT(onPopupWarning(QString)), Qt::BlockingQueuedConnection);

          Here the signal is sent from engineThread & slot is in gui thread. Since you are passing blocked queued connection, engine thread will hang till slot is complete. Here inside the slot you are calling message box. unless you close message box, slot is not finished.

          Hence you have threads are blocked. Hope it helps.

          M Offline
          M Offline
          mr.indieperson
          wrote on last edited by
          #4

          @dheerendra I want this behavior and it works fine, as I said, if I emit the signal just somewhere outside OpenGL function call. If I see a message box, both engine and gui threads wait until I have clicked OK. But If an error occurres in OpenGL function call and there are two signals described above are emitted, I cannot see a Message Box, so I can't continue the execution of both the threads

          1 Reply Last reply
          0
          • kshegunovK kshegunov

            Check that the threads on emission and reception are indeed different. The stack you provided is for the GUI thread only, consider extracting the trace for the two threads to see where it locks and why.

            M Offline
            M Offline
            mr.indieperson
            wrote on last edited by
            #5

            @kshegunov the threads are indeed different and the engine thread is locked because of blocking queue connection at signal emitting at one line in both cases, the engine thread works fine, stack traces are equal for it, i cannot show it now

            kshegunovK 1 Reply Last reply
            0
            • M mr.indieperson

              @kshegunov the threads are indeed different and the engine thread is locked because of blocking queue connection at signal emitting at one line in both cases, the engine thread works fine, stack traces are equal for it, i cannot show it now

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

              Fastest thing to check - use the default Qt::QueuedConnection. If you deadlock it's not your connect, otherwise it's something about the connection (like having the objects in the same thread and using Qt::BlockingQueuedConnection).

              Read and abide by the Qt Code of Conduct

              M 2 Replies Last reply
              1
              • kshegunovK kshegunov

                Fastest thing to check - use the default Qt::QueuedConnection. If you deadlock it's not your connect, otherwise it's something about the connection (like having the objects in the same thread and using Qt::BlockingQueuedConnection).

                M Offline
                M Offline
                mr.indieperson
                wrote on last edited by
                #7

                @kshegunov i've checked simple QueuedConnection. Now i see MessageBoxes successfully in both cases: i emit a warningSignalEmitter.popuped(..) signal manually outside of OpenGL function calls AND the QOpenGLDebugLogger emits a messageLogged(..) signal, and in its slot a warningSignalEmitter.popuped(..) signal is emitted. The engine threads just triggers these emittings and continue its execution, what is not good. And the GUI thread shows me both MessageBox at the same time.

                When i switch back to BlockingQueuedConnection, as i described earlier, only emittings outside the OpenGL function calls works fine and i can see a MessageBox and continue execution of both engine and GUI threads, and if a signal is emitted inside OpenGL functions call, i don't see a MessageBox.

                1 Reply Last reply
                0
                • kshegunovK kshegunov

                  Fastest thing to check - use the default Qt::QueuedConnection. If you deadlock it's not your connect, otherwise it's something about the connection (like having the objects in the same thread and using Qt::BlockingQueuedConnection).

                  M Offline
                  M Offline
                  mr.indieperson
                  wrote on last edited by mr.indieperson
                  #8

                  @kshegunov And i've figured out one thing. If i emit QOpenGLDebugLogger::messageLogged(..) manually outside of OpenGL function calls, none deadlock happens and i see a MessageBox, but if the signal is emitted because of some error in an OpenGL functions call, and so the signal emitting has its place in the stack trace after the OpenGL function call, so the deadlock happens and i don't see a MessageBox. So it seems that if i try to use GUI after some OpenGL functions calls, the GUI becomes broken due to inner errors. I have no idea how to fix it, but only to left this idea and use error logging and notificating in old manner: place calls after each OpenGL function call or its group. Or don't use the GUI and just log errors in some stream.

                  Cobra91151C kshegunovK 2 Replies Last reply
                  0
                  • M mr.indieperson

                    @kshegunov And i've figured out one thing. If i emit QOpenGLDebugLogger::messageLogged(..) manually outside of OpenGL function calls, none deadlock happens and i see a MessageBox, but if the signal is emitted because of some error in an OpenGL functions call, and so the signal emitting has its place in the stack trace after the OpenGL function call, so the deadlock happens and i don't see a MessageBox. So it seems that if i try to use GUI after some OpenGL functions calls, the GUI becomes broken due to inner errors. I have no idea how to fix it, but only to left this idea and use error logging and notificating in old manner: place calls after each OpenGL function call or its group. Or don't use the GUI and just log errors in some stream.

                    Cobra91151C Offline
                    Cobra91151C Offline
                    Cobra91151
                    wrote on last edited by Cobra91151
                    #9

                    @mr.indieperson

                    Hi! You can try to create your QMessageBox as a pointer. For example:

                    QMessageBox *msgBox = new QMessageBox(this);
                    msgBox->setWindowModality(Qt::ApplicationModal);
                    msgBox->setText("This is a test!");
                    msgBox->show();
                    

                    This way you can customize your msgbox. Then in the destructor call delete msgBox to free the resources.

                    Also you can check where the deadlock occurs using qDebug() (http://doc.qt.io/qt-5/qdebug.html), place for example: qDebug() << "Test1"; in your signals/slots and then run the program, you will know what is going on in the code.

                    M 1 Reply Last reply
                    0
                    • Cobra91151C Cobra91151

                      @mr.indieperson

                      Hi! You can try to create your QMessageBox as a pointer. For example:

                      QMessageBox *msgBox = new QMessageBox(this);
                      msgBox->setWindowModality(Qt::ApplicationModal);
                      msgBox->setText("This is a test!");
                      msgBox->show();
                      

                      This way you can customize your msgbox. Then in the destructor call delete msgBox to free the resources.

                      Also you can check where the deadlock occurs using qDebug() (http://doc.qt.io/qt-5/qdebug.html), place for example: qDebug() << "Test1"; in your signals/slots and then run the program, you will know what is going on in the code.

                      M Offline
                      M Offline
                      mr.indieperson
                      wrote on last edited by
                      #10

                      @Cobra91151 thanks, but this doesn't work. MessageBox is deadlocked at show(), if an OpenGL error has occured earlier in a stack trace. And i've learned all i could with debugging.

                      1 Reply Last reply
                      0
                      • M mr.indieperson

                        @kshegunov And i've figured out one thing. If i emit QOpenGLDebugLogger::messageLogged(..) manually outside of OpenGL function calls, none deadlock happens and i see a MessageBox, but if the signal is emitted because of some error in an OpenGL functions call, and so the signal emitting has its place in the stack trace after the OpenGL function call, so the deadlock happens and i don't see a MessageBox. So it seems that if i try to use GUI after some OpenGL functions calls, the GUI becomes broken due to inner errors. I have no idea how to fix it, but only to left this idea and use error logging and notificating in old manner: place calls after each OpenGL function call or its group. Or don't use the GUI and just log errors in some stream.

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

                        @mr.indieperson said in Deadlocked QMessageBox doesn't appear at signal processing:

                        And i've figured out one thing.

                        Me too, I think. Where do you emit QOpenGLDebugLogger::messageLogged?

                        Read and abide by the Qt Code of Conduct

                        M 2 Replies Last reply
                        0
                        • kshegunovK kshegunov

                          @mr.indieperson said in Deadlocked QMessageBox doesn't appear at signal processing:

                          And i've figured out one thing.

                          Me too, I think. Where do you emit QOpenGLDebugLogger::messageLogged?

                          M Offline
                          M Offline
                          mr.indieperson
                          wrote on last edited by
                          #12
                          This post is deleted!
                          1 Reply Last reply
                          0
                          • kshegunovK kshegunov

                            @mr.indieperson said in Deadlocked QMessageBox doesn't appear at signal processing:

                            And i've figured out one thing.

                            Me too, I think. Where do you emit QOpenGLDebugLogger::messageLogged?

                            M Offline
                            M Offline
                            mr.indieperson
                            wrote on last edited by mr.indieperson
                            #13

                            @kshegunov So i've written a program, demonstrating the issue. I've posted source files in a bug report, its link below. If you run the program, make sure you've reached "OpenGL has inited!" message.

                            I've learned, that not all errors cause a deadlock, the program demonstrates this too. So it seems for me like a bug: the program behaves differently in similar situations, looks like unexpected/undefined behavior. I've decided to report about this issue, they will figure this out: https://bugreports.qt.io/browse/QTBUG-69780

                            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