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

QWaitCondition causes app the crash

Scheduled Pinned Locked Moved Solved General and Desktop
13 Posts 5 Posters 2.0k 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 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