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. QWaitCondition causes app the crash
Forum Updated to NodeBB v4.3 + New Features

QWaitCondition causes app the crash

Scheduled Pinned Locked Moved Solved General and Desktop
13 Posts 5 Posters 1.6k 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.
  • S Offline
    S Offline
    Steve_Lim
    wrote on last edited by
    #1

    Hi guys,

    I have been experimenting with QWaitCondition. The app crashes upon launching.

    This is a 2 thread program where 1 thread is allocated for transmitter and the other for receiver.

    The error message: The program has unexpectedly finished.

    Transmitter:

        mutex->lock();
        qDebug() << "Initiate 3 way handshake";
        sReady->wakeAll();
        qDebug() << "Transmitter: Ready";
        mutex->unlock();
    

    Receiver:

        mutex->lock();
        qDebug() << "Receiver";
        sReady->wait(mutex);
        qDebug() << "wake";
        mutex->unlock();
    

    Thank you very much :)

    1 Reply Last reply
    0
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Use a debugger, I would guess mutex is not initialized.

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      1 Reply Last reply
      0
      • S Offline
        S Offline
        Steve_Lim
        wrote on last edited by
        #3

        Hi, I have run with debugger, it says Segmentation fault.

        Is there a particular reason why? Because what I did was just ask the thread to wait and wake up.

        jsulmJ 1 Reply Last reply
        0
        • S Steve_Lim

          Hi, I have run with debugger, it says Segmentation fault.

          Is there a particular reason why? Because what I did was just ask the thread to wait and wake up.

          jsulmJ Offline
          jsulmJ Offline
          jsulm
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @Steve_Lim said in QWaitCondition causes app the crash:

          it says Segmentation fault

          Where exactly? Which line in your code?

          https://forum.qt.io/topic/113070/qt-code-of-conduct

          S 1 Reply Last reply
          0
          • jsulmJ jsulm

            @Steve_Lim said in QWaitCondition causes app the crash:

            it says Segmentation fault

            Where exactly? Which line in your code?

            S Offline
            S Offline
            Steve_Lim
            wrote on last edited by
            #5

            @jsulm This is the pop up error message:

            The inferior stopped because it received a signal from the operating system.

            Signal name :
            SIGSEGV
            Signal meaning :
            Segmentation fault

            At below debugger, where the header are level and function:
            1)QWaitCondition::WakeAll()
            2) ??
            3) ??
            4) QMetaCallEvent::placeMetaCall(QObject*)
            ...

            I hope this is what you are looking for. I am new to all these stuff, apologise if its not useful

            JonBJ 1 Reply Last reply
            0
            • S Steve_Lim

              @jsulm This is the pop up error message:

              The inferior stopped because it received a signal from the operating system.

              Signal name :
              SIGSEGV
              Signal meaning :
              Segmentation fault

              At below debugger, where the header are level and function:
              1)QWaitCondition::WakeAll()
              2) ??
              3) ??
              4) QMetaCallEvent::placeMetaCall(QObject*)
              ...

              I hope this is what you are looking for. I am new to all these stuff, apologise if its not useful

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by
              #6

              @Steve_Lim
              We really need see the stack trace higher up then you show: can you expand what you show as the ... at the end, such that eventually it shows some line/function in your own code where this is being called from?

              Meanwhile, from what I see I suspect this is being called from your transmitter's sReady->wakeAll(); statement. Is sReady valid at this point? You need to ensure that it is a valid QWaitCondition, e.g. it must not have been deleted or gone out of scope.

              S 1 Reply Last reply
              4
              • JonBJ JonB

                @Steve_Lim
                We really need see the stack trace higher up then you show: can you expand what you show as the ... at the end, such that eventually it shows some line/function in your own code where this is being called from?

                Meanwhile, from what I see I suspect this is being called from your transmitter's sReady->wakeAll(); statement. Is sReady valid at this point? You need to ensure that it is a valid QWaitCondition, e.g. it must not have been deleted or gone out of scope.

                S Offline
                S Offline
                Steve_Lim
                wrote on last edited by
                #7

                @JonB This is the full lines:

                1. QWaitCondition::wakeAll()
                2. ??
                3. ??
                4. QMetaCallEvent::placeMetaCall(QObject *)
                5. QObject::event(QEvent *)
                6. QApplicationPrivate::notify_helper(QObject *, QEvent *)
                7. QApplication::notify(QObject *, QEvent *)
                8. QCoreApplication::notifyInternal2(QObject *, QEvent *)
                9. QCoreApplicationPrivate::sendPostedEvents(QObject *, int, QThreaD...
                  ... QEventDispatcherWin32::processEvents(QFlags<QEventLoop::Process...
                  ...QEventLoop::exec(QFlagQEventLoop::ProcessEventsFlag)
                  ...QThread::run()
                  ...QThreadPrivate::start(void *)
                  ... KERNEL32!BaseThreadInitThunk
                  ... ntdll!RtlUserThreadStart
                  ... ??

                I think it would be best to let me explain how I pass the variables, to see if I made any mistake there.

                So, there are 3 files, one for main.cpp, the others are transmit.cpp and receiver.cpp.

                This is part of the code in my file:
                main.cpp:

                QWaitCondition *sendState; // transmitter state
                QWaitCondition *receiveState; // receiver state
                int main(int argc, char *argv[]) {
                    QThread transmitThread;
                    QThread receiveThread;
                
                    QMutex mutex;
                
                    transmit *transmitter = new transmit();
                    receiver *receive = new receiver();
                
                    // move each object to their threads
                    transmitter->moveToThread(&transmitThread);
                    receive->moveToThread(&receiveThread);
                
                    transmitter->init(sendState, receiveState, &mutex);
                    receive->init(sendState, receiveState, &mutex,);
                
                    transmitThread.start();
                    receiveThread.start();
                }
                

                Transmitter:

                void transmit::init( QWaitCondition *sendPin, QWaitCondition *receivePin, QMutex *mtx) {
                
                    // All has been declared at .h to be pointer eg: QMutex *mutex
                    sent = sendPin; // sent state from transmitter
                    receive = receivePin; // receive state from receiver
                    mutex = mtx; // mutex from main
                }
                
                // Follow with what is posted originally inside another function
                

                Receiver:
                Same as transmiter::init, and the other function was what posted originally

                Hope this helps, thank you.

                JonBJ 1 Reply Last reply
                0
                • S Steve_Lim

                  @JonB This is the full lines:

                  1. QWaitCondition::wakeAll()
                  2. ??
                  3. ??
                  4. QMetaCallEvent::placeMetaCall(QObject *)
                  5. QObject::event(QEvent *)
                  6. QApplicationPrivate::notify_helper(QObject *, QEvent *)
                  7. QApplication::notify(QObject *, QEvent *)
                  8. QCoreApplication::notifyInternal2(QObject *, QEvent *)
                  9. QCoreApplicationPrivate::sendPostedEvents(QObject *, int, QThreaD...
                    ... QEventDispatcherWin32::processEvents(QFlags<QEventLoop::Process...
                    ...QEventLoop::exec(QFlagQEventLoop::ProcessEventsFlag)
                    ...QThread::run()
                    ...QThreadPrivate::start(void *)
                    ... KERNEL32!BaseThreadInitThunk
                    ... ntdll!RtlUserThreadStart
                    ... ??

                  I think it would be best to let me explain how I pass the variables, to see if I made any mistake there.

                  So, there are 3 files, one for main.cpp, the others are transmit.cpp and receiver.cpp.

                  This is part of the code in my file:
                  main.cpp:

                  QWaitCondition *sendState; // transmitter state
                  QWaitCondition *receiveState; // receiver state
                  int main(int argc, char *argv[]) {
                      QThread transmitThread;
                      QThread receiveThread;
                  
                      QMutex mutex;
                  
                      transmit *transmitter = new transmit();
                      receiver *receive = new receiver();
                  
                      // move each object to their threads
                      transmitter->moveToThread(&transmitThread);
                      receive->moveToThread(&receiveThread);
                  
                      transmitter->init(sendState, receiveState, &mutex);
                      receive->init(sendState, receiveState, &mutex,);
                  
                      transmitThread.start();
                      receiveThread.start();
                  }
                  

                  Transmitter:

                  void transmit::init( QWaitCondition *sendPin, QWaitCondition *receivePin, QMutex *mtx) {
                  
                      // All has been declared at .h to be pointer eg: QMutex *mutex
                      sent = sendPin; // sent state from transmitter
                      receive = receivePin; // receive state from receiver
                      mutex = mtx; // mutex from main
                  }
                  
                  // Follow with what is posted originally inside another function
                  

                  Receiver:
                  Same as transmiter::init, and the other function was what posted originally

                  Hope this helps, thank you.

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by
                  #8

                  @Steve_Lim
                  As stated earlier, I see no evidence from this code that QWaitCondition *sendState or QWaitCondition *receiveState are ever set to any QWaitCondition. Which would make sReady->wakeAll(); a call on an uninitialized QWaitCondition.

                  S 1 Reply Last reply
                  3
                  • JonBJ JonB

                    @Steve_Lim
                    As stated earlier, I see no evidence from this code that QWaitCondition *sendState or QWaitCondition *receiveState are ever set to any QWaitCondition. Which would make sReady->wakeAll(); a call on an uninitialized QWaitCondition.

                    S Offline
                    S Offline
                    Steve_Lim
                    wrote on last edited by
                    #9

                    @JonB Oh my...., that feels like a rookie mistake. Making QWaitCondition sendState = new QWaitCondition() solves all the issues.

                    Thank you very much

                    1 Reply Last reply
                    1
                    • S Offline
                      S Offline
                      SimonSchroeder
                      wrote on last edited by
                      #10

                      I am not entirely sure what exactly happens in your little main function. However, I suspect there might be lurking some more trouble. First of all, you have 3 threads in total: Every application has a single thread when it starts and you are adding two more. I don't see your application waiting at the end of main. Does anyone know if the destructor of QThread will be blocking? Otherwise your program will exit right after calling receiveThread.start() calling the destructors of transmitThread, receiveThread and mutex as these are all on the stack.

                      I hope this is just a small reduced example of your real software and does not reflect what you are planning to do.

                      S 1 Reply Last reply
                      0
                      • S SimonSchroeder

                        I am not entirely sure what exactly happens in your little main function. However, I suspect there might be lurking some more trouble. First of all, you have 3 threads in total: Every application has a single thread when it starts and you are adding two more. I don't see your application waiting at the end of main. Does anyone know if the destructor of QThread will be blocking? Otherwise your program will exit right after calling receiveThread.start() calling the destructors of transmitThread, receiveThread and mutex as these are all on the stack.

                        I hope this is just a small reduced example of your real software and does not reflect what you are planning to do.

                        S Offline
                        S Offline
                        Steve_Lim
                        wrote on last edited by
                        #11

                        @SimonSchroeder At the end of the main.cpp I have these few lines. Not sure if this is the correct way to quit thread and mutex.

                            transmitThread.quit();
                            transmitThread.terminate();
                        
                            receiveThread.quit();
                            receiveThread.terminate();
                        
                            mutex.~QMutex();
                        
                        S 1 Reply Last reply
                        0
                        • S Steve_Lim

                          @SimonSchroeder At the end of the main.cpp I have these few lines. Not sure if this is the correct way to quit thread and mutex.

                              transmitThread.quit();
                              transmitThread.terminate();
                          
                              receiveThread.quit();
                              receiveThread.terminate();
                          
                              mutex.~QMutex();
                          
                          S Offline
                          S Offline
                          SimonSchroeder
                          wrote on last edited by
                          #12

                          @Steve_Lim A QThread starts an internal event loop. Calling quit() on it enqueues a signal to that queue to stop the thread. If you don't have a slot running inside the event queue of the thread (a lot of people will write an infinite loop to run in that thread) then the quit request will be handled eventually. Calling terminate() on the thread is not such a good idea, though. It will kill the thread as fast as possible interrupting any work it was doing. This might leave some shared variables in an undefined state. Only use terminate() if there is no other way (and your really don't need it here). Instead you should call wait() on the thread to wait until it has actually finished (as you have called quit() before).

                          Finally, mutex is a local variable. Its destructor will be called when it goes out of scope. As you call it explicitly it will be called twice. This is a really bad idea. As a general rule of thumb you never call the destructor explicitly (one rare exception is when you write your own vector class managing objects). For stack variables the destructor gets called when the variable goes out of scope and for heap variables (hopefully allocated with new) the destructor gets call automatically when delete is called.

                          Here is how I would write the last lines of main:

                          transmitThread.quit();
                          receiveThread.quit();
                          
                          transmitThread.wait();
                          receiveThread.wait();
                          
                          S 1 Reply Last reply
                          1
                          • S SimonSchroeder

                            @Steve_Lim A QThread starts an internal event loop. Calling quit() on it enqueues a signal to that queue to stop the thread. If you don't have a slot running inside the event queue of the thread (a lot of people will write an infinite loop to run in that thread) then the quit request will be handled eventually. Calling terminate() on the thread is not such a good idea, though. It will kill the thread as fast as possible interrupting any work it was doing. This might leave some shared variables in an undefined state. Only use terminate() if there is no other way (and your really don't need it here). Instead you should call wait() on the thread to wait until it has actually finished (as you have called quit() before).

                            Finally, mutex is a local variable. Its destructor will be called when it goes out of scope. As you call it explicitly it will be called twice. This is a really bad idea. As a general rule of thumb you never call the destructor explicitly (one rare exception is when you write your own vector class managing objects). For stack variables the destructor gets called when the variable goes out of scope and for heap variables (hopefully allocated with new) the destructor gets call automatically when delete is called.

                            Here is how I would write the last lines of main:

                            transmitThread.quit();
                            receiveThread.quit();
                            
                            transmitThread.wait();
                            receiveThread.wait();
                            
                            S Offline
                            S Offline
                            Steve_Lim
                            wrote on last edited by
                            #13

                            @SimonSchroeder Thank you for the explaination. I did inside my transmitter and receiver class create another function that is called when a window is closed.

                            Since the receiver keeps on running and never stop, I figure it is a good idea to put an if statement where when the window is closed, it will stop the receiver from running for another time.

                            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