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. How to properly quit blocking thread
QtWS25 Last Chance

How to properly quit blocking thread

Scheduled Pinned Locked Moved Solved General and Desktop
qthread
27 Posts 6 Posters 5.1k 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.
  • J Offline
    J Offline
    JeKK666
    wrote on 4 Apr 2022, 08:23 last edited by
    #1

    I have a Qthread that blocks, waiting to read hardware, like this:

    void MyThread::run() {
        while (1) {
            poll(...);
        }
    }
    

    Suppose i need to stop said thread to change some configuration and restart it, how would i go about it?

    I've read the docs for QThread, found about methods quit(), exit() and terminate(), but there are two aspects i don't get:

    1. is the main thread supposed to call t.quit() where t is an object of type MyThread, just as i have invoked t.start()? Or does t have to call quit itself, inside its event loop?
    2. this being a blocking thread with an infinite loop, if the main thread calls t.quit(), is it ever gonna execute and terminate the event loop, so it can be restarted later? Or do i have to put a flag inside the while(1){...} to check if i need to stop?

    Still haven't learned Lambdas...

    J 1 Reply Last reply 4 Apr 2022, 08:30
    0
    • J JeKK666
      4 Apr 2022, 10:28

      @JonB i need to block indefinetely, unless a configuration changes, which will require changing how the sysfs endpoint are polled, and therefore run a slightly modified version of the thread code; i think my best option is going to be trying to throw a fake interrupt, so as to have the code react to isInterruptionRequested().

      Thanks everyone for the insights and suggestions :)

      J Offline
      J Offline
      JonB
      wrote on 4 Apr 2022, 10:42 last edited by
      #20

      @JeKK666 said in How to properly quit blocking thread:

      @JonB i need to block indefinetely, unless a configuration changes, which will require changing how the sysfs endpoint are polled, and therefore run a slightly modified version of the thread code; i think my best option is going to be trying to throw a fake interrupt, so as to have the code react to isInterruptionRequested().

      Indeed you can do it that way, raising a (Linux) signal() from the main thread to interrupt the poll() in the other thread. And if that is what you want or need to do, fine.

      However it is not unusual to write code which calls poll() with a timeout and then restart the poll if it timed out. Code like:

      void MyThread::run() {
          while(!isInterruptionRequested()) {
              // do stuff here, including...
              if (poll(..., timeout) != 0)
              {
                   // genuine arrival of data, *not* timeout
                   // if timeout occurs, code goes through the `while` again
                   // which first checks for `isInterruptionRequested()` and then re starts a new `poll(..., timeout)`
              }
          }    
      }
      

      per the doc's

      A return value of zero indicates that the system call timed out

      before any file descriptors became read.

      1 Reply Last reply
      1
      • J JeKK666
        4 Apr 2022, 08:23

        I have a Qthread that blocks, waiting to read hardware, like this:

        void MyThread::run() {
            while (1) {
                poll(...);
            }
        }
        

        Suppose i need to stop said thread to change some configuration and restart it, how would i go about it?

        I've read the docs for QThread, found about methods quit(), exit() and terminate(), but there are two aspects i don't get:

        1. is the main thread supposed to call t.quit() where t is an object of type MyThread, just as i have invoked t.start()? Or does t have to call quit itself, inside its event loop?
        2. this being a blocking thread with an infinite loop, if the main thread calls t.quit(), is it ever gonna execute and terminate the event loop, so it can be restarted later? Or do i have to put a flag inside the while(1){...} to check if i need to stop?
        J Offline
        J Offline
        jsulm
        Lifetime Qt Champion
        wrote on 4 Apr 2022, 08:30 last edited by
        #2

        @JeKK666 See https://doc.qt.io/qt-5/qthread.html#requestInterruption

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

        1 Reply Last reply
        3
        • J Offline
          J Offline
          JeKK666
          wrote on 4 Apr 2022, 09:17 last edited by JeKK666 4 Apr 2022, 09:22
          #3

          So i have to put an if inside the loop, like this:

          void MyThread::run() {
              while (1) {
                  poll(...);
                  if (isInterruptionRequested()) {
                      quit();
                  }
              }
          }
          

          ?

          But since the call to poll() is blocking, the only way it could get to the if statement would be in consequence of an event, which may or may not occur...
          Is there a way to ... uhm... cleanly force terminate the thread? XD

          Still haven't learned Lambdas...

          J K J 3 Replies Last reply 4 Apr 2022, 09:37
          0
          • S Offline
            S Offline
            SGaist
            Lifetime Qt Champion
            wrote on 4 Apr 2022, 09:33 last edited by
            #4

            Hi,

            Then you should use a proper timeout and handle that case. There's no clean thread termination if you have to kill it.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            1
            • J JeKK666
              4 Apr 2022, 09:17

              So i have to put an if inside the loop, like this:

              void MyThread::run() {
                  while (1) {
                      poll(...);
                      if (isInterruptionRequested()) {
                          quit();
                      }
                  }
              }
              

              ?

              But since the call to poll() is blocking, the only way it could get to the if statement would be in consequence of an event, which may or may not occur...
              Is there a way to ... uhm... cleanly force terminate the thread? XD

              J Offline
              J Offline
              JonB
              wrote on 4 Apr 2022, 09:37 last edited by
              #5

              @JeKK666 said in How to properly quit blocking thread:

              But since the call to poll() is blocking

              Really? The point of a poll is to test and return immediately with a "yes" or "no", not to block!

              J J 2 Replies Last reply 4 Apr 2022, 09:42
              0
              • J JonB
                4 Apr 2022, 09:37

                @JeKK666 said in How to properly quit blocking thread:

                But since the call to poll() is blocking

                Really? The point of a poll is to test and return immediately with a "yes" or "no", not to block!

                J Offline
                J Offline
                jsulm
                Lifetime Qt Champion
                wrote on 4 Apr 2022, 09:42 last edited by
                #6

                @JonB said in How to properly quit blocking thread:

                The point of a poll is to test and return immediately with a "yes" or "no", not to block!

                Not really (man poll):
                "If none of the events requested (and no error) has occurred for any of the file descriptors, then poll() blocks until one of the events occurs."

                But there is timeout parameter to prevent poll from blocking for longer time.

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

                J 1 Reply Last reply 4 Apr 2022, 10:07
                2
                • J JonB
                  4 Apr 2022, 09:37

                  @JeKK666 said in How to properly quit blocking thread:

                  But since the call to poll() is blocking

                  Really? The point of a poll is to test and return immediately with a "yes" or "no", not to block!

                  J Offline
                  J Offline
                  JeKK666
                  wrote on 4 Apr 2022, 09:45 last edited by
                  #7

                  @JonB Then i guess those who invented sysfs got it wrong, somehow 😝

                  @SGaist uhm...fair enough, unfortunately it's a system which waits for user input, which may or may not come in, say, a day, and there's the possibility i need to change the software configuration before said interaction. I'll have to come up with something, perhaps i can trick the system into registering a fake interrupt of sorts and have poll() return as needed, on my own terms 😉

                  Still haven't learned Lambdas...

                  1 Reply Last reply
                  0
                  • J JeKK666
                    4 Apr 2022, 09:17

                    So i have to put an if inside the loop, like this:

                    void MyThread::run() {
                        while (1) {
                            poll(...);
                            if (isInterruptionRequested()) {
                                quit();
                            }
                        }
                    }
                    

                    ?

                    But since the call to poll() is blocking, the only way it could get to the if statement would be in consequence of an event, which may or may not occur...
                    Is there a way to ... uhm... cleanly force terminate the thread? XD

                    K Offline
                    K Offline
                    KroMignon
                    wrote on 4 Apr 2022, 09:49 last edited by KroMignon 4 Apr 2022, 09:49
                    #8

                    @JeKK666 said in How to properly quit blocking thread:

                    void MyThread::run() {
                        while (1) {
                            poll(...);
                            if (isInterruptionRequested()) {
                                quit();
                            }
                        }
                    }
                    

                    Not really, I would do it like this:

                    void MyThread::run() {
                        while(!isInterruptionRequested()) {
                            // do stuff here
                        }    
                    }
                    

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

                    J 1 Reply Last reply 4 Apr 2022, 10:06
                    1
                    • J JeKK666
                      4 Apr 2022, 09:17

                      So i have to put an if inside the loop, like this:

                      void MyThread::run() {
                          while (1) {
                              poll(...);
                              if (isInterruptionRequested()) {
                                  quit();
                              }
                          }
                      }
                      

                      ?

                      But since the call to poll() is blocking, the only way it could get to the if statement would be in consequence of an event, which may or may not occur...
                      Is there a way to ... uhm... cleanly force terminate the thread? XD

                      J Offline
                      J Offline
                      J.Hilk
                      Moderators
                      wrote on 4 Apr 2022, 09:55 last edited by
                      #9

                      @JeKK666 said in How to properly quit blocking thread:

                      quit

                      since you're not using the QEventLoop, that QThread provides, calling quit() will have no effect. The threat should keep on running. You'll have to call break or return


                      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                      Q: What's that?
                      A: It's blue light.
                      Q: What does it do?
                      A: It turns blue.

                      1 Reply Last reply
                      1
                      • K KroMignon
                        4 Apr 2022, 09:49

                        @JeKK666 said in How to properly quit blocking thread:

                        void MyThread::run() {
                            while (1) {
                                poll(...);
                                if (isInterruptionRequested()) {
                                    quit();
                                }
                            }
                        }
                        

                        Not really, I would do it like this:

                        void MyThread::run() {
                            while(!isInterruptionRequested()) {
                                // do stuff here
                            }    
                        }
                        
                        J Offline
                        J Offline
                        JeKK666
                        wrote on 4 Apr 2022, 10:06 last edited by
                        #10

                        @KroMignon
                        ...speechless... thank you for putting me in front of my own dumbness, this is exaclty what i need and apparentely could not figure out by myself :O

                        Still haven't learned Lambdas...

                        J 1 Reply Last reply 4 Apr 2022, 10:11
                        0
                        • J jsulm
                          4 Apr 2022, 09:42

                          @JonB said in How to properly quit blocking thread:

                          The point of a poll is to test and return immediately with a "yes" or "no", not to block!

                          Not really (man poll):
                          "If none of the events requested (and no error) has occurred for any of the file descriptors, then poll() blocks until one of the events occurs."

                          But there is timeout parameter to prevent poll from blocking for longer time.

                          J Offline
                          J Offline
                          JonB
                          wrote on 4 Apr 2022, 10:07 last edited by
                          #11

                          @jsulm , @JeKK666
                          Fine, let me try again. If you are using the Linux poll() system call, that has a "timeout" parameter which allows you to test and return, right? If you are using some other poll() function does it offer a similar option?

                          J 1 Reply Last reply 4 Apr 2022, 10:16
                          0
                          • J JeKK666
                            4 Apr 2022, 10:06

                            @KroMignon
                            ...speechless... thank you for putting me in front of my own dumbness, this is exaclty what i need and apparentely could not figure out by myself :O

                            J Offline
                            J Offline
                            JonB
                            wrote on 4 Apr 2022, 10:11 last edited by JonB 4 Apr 2022, 10:12
                            #12

                            @JeKK666 said in How to properly quit blocking thread:

                            @KroMignon
                            ...speechless... thank you for putting me in front of my own dumbness, this is exaclty what i need and apparentely could not figure out by myself :O

                            I do not see the difference of behaviour between

                            void MyThread::run() {
                                while (1) {
                                    poll(...);
                                    if (isInterruptionRequested()) {
                                        quit();
                                    }
                                }
                            }
                            

                            and

                            void MyThread::run() {
                                while(!isInterruptionRequested()) {
                                    // do stuff here, including...
                                    poll(...);
                                }    
                            }
                            

                            if your poll() is blocking as you said. [Yes the second avoids the quit() if no event loop, but not poll() blocking and failing to see isInterruptionRequested().]

                            J K 2 Replies Last reply 4 Apr 2022, 10:13
                            1
                            • J JonB
                              4 Apr 2022, 10:11

                              @JeKK666 said in How to properly quit blocking thread:

                              @KroMignon
                              ...speechless... thank you for putting me in front of my own dumbness, this is exaclty what i need and apparentely could not figure out by myself :O

                              I do not see the difference of behaviour between

                              void MyThread::run() {
                                  while (1) {
                                      poll(...);
                                      if (isInterruptionRequested()) {
                                          quit();
                                      }
                                  }
                              }
                              

                              and

                              void MyThread::run() {
                                  while(!isInterruptionRequested()) {
                                      // do stuff here, including...
                                      poll(...);
                                  }    
                              }
                              

                              if your poll() is blocking as you said. [Yes the second avoids the quit() if no event loop, but not poll() blocking and failing to see isInterruptionRequested().]

                              J Offline
                              J Offline
                              JeKK666
                              wrote on 4 Apr 2022, 10:13 last edited by
                              #13

                              @JonB yikes... that's right

                              Still haven't learned Lambdas...

                              1 Reply Last reply
                              0
                              • J JonB
                                4 Apr 2022, 10:07

                                @jsulm , @JeKK666
                                Fine, let me try again. If you are using the Linux poll() system call, that has a "timeout" parameter which allows you to test and return, right? If you are using some other poll() function does it offer a similar option?

                                J Offline
                                J Offline
                                JeKK666
                                wrote on 4 Apr 2022, 10:16 last edited by
                                #14

                                @JonB i'm indeed using the Linux poll() detailed in man section 2, excerpt:

                                poll() performs a similar task to select(2): it waits for one of a set of file descriptors to become ready to perform I/O.
                                

                                I need it to block indefinetely until a HW interrupt occurs.

                                Still haven't learned Lambdas...

                                J 1 Reply Last reply 4 Apr 2022, 10:19
                                0
                                • J JonB
                                  4 Apr 2022, 10:11

                                  @JeKK666 said in How to properly quit blocking thread:

                                  @KroMignon
                                  ...speechless... thank you for putting me in front of my own dumbness, this is exaclty what i need and apparentely could not figure out by myself :O

                                  I do not see the difference of behaviour between

                                  void MyThread::run() {
                                      while (1) {
                                          poll(...);
                                          if (isInterruptionRequested()) {
                                              quit();
                                          }
                                      }
                                  }
                                  

                                  and

                                  void MyThread::run() {
                                      while(!isInterruptionRequested()) {
                                          // do stuff here, including...
                                          poll(...);
                                      }    
                                  }
                                  

                                  if your poll() is blocking as you said. [Yes the second avoids the quit() if no event loop, but not poll() blocking and failing to see isInterruptionRequested().]

                                  K Offline
                                  K Offline
                                  KroMignon
                                  wrote on 4 Apr 2022, 10:17 last edited by
                                  #15

                                  @JonB said in How to properly quit blocking thread:

                                  if your poll() is blocking as you said. [Yes the second avoids the quit() if no event loop, but not poll() blocking and failing to see isInterruptionRequested().]

                                  Using quit() don't make sense here. This thread do not have an event loop, so not signals/slots can be used here.

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

                                  J 1 Reply Last reply 4 Apr 2022, 10:20
                                  0
                                  • J JeKK666
                                    4 Apr 2022, 10:16

                                    @JonB i'm indeed using the Linux poll() detailed in man section 2, excerpt:

                                    poll() performs a similar task to select(2): it waits for one of a set of file descriptors to become ready to perform I/O.
                                    

                                    I need it to block indefinetely until a HW interrupt occurs.

                                    J Offline
                                    J Offline
                                    JonB
                                    wrote on 4 Apr 2022, 10:19 last edited by JonB 4 Apr 2022, 10:21
                                    #16

                                    @JeKK666
                                    man 2 poll:

                                    int poll(struct pollfd *fds, nfds_t nfds, int timeout);
                                    
                                       The timeout argument specifies the number of milliseconds that
                                    
                                       poll() should block waiting for a file descriptor to become
                                    
                                       ready.  The call will block until either:
                                    
                                    
                                    
                                       • a file descriptor becomes ready;
                                    
                                    
                                    
                                       • the call is interrupted by a signal handler; or
                                    
                                    
                                    
                                       • the timeout expires.
                                    

                                    You need to pass a timeout.

                                    I need it to block indefinetely until a HW interrupt occurs.

                                    If that were 100% true you would not be asking about how to interrupt the thread with isInterruptionRequested().

                                    J 1 Reply Last reply 4 Apr 2022, 10:28
                                    2
                                    • K KroMignon
                                      4 Apr 2022, 10:17

                                      @JonB said in How to properly quit blocking thread:

                                      if your poll() is blocking as you said. [Yes the second avoids the quit() if no event loop, but not poll() blocking and failing to see isInterruptionRequested().]

                                      Using quit() don't make sense here. This thread do not have an event loop, so not signals/slots can be used here.

                                      J Offline
                                      J Offline
                                      JonB
                                      wrote on 4 Apr 2022, 10:20 last edited by JonB 4 Apr 2022, 10:22
                                      #17

                                      @KroMignon said in How to properly quit blocking thread:

                                      @JonB said in How to properly quit blocking thread:

                                      if your poll() is blocking as you said. [Yes the second avoids the quit() if no event loop, but not poll() blocking and failing to see isInterruptionRequested().]

                                      Using quit() don't make sense here. This thread do not have an event loop, so not signals/slots can be used here.

                                      Absolutely which is why I wrote what I did: your code is definitely better in that it does not attempt to use a useless quit(), but since the OP wants (thought he wanted) a blocking poll() call into the body it won't address that problem.

                                      K 1 Reply Last reply 4 Apr 2022, 10:28
                                      1
                                      • J JonB
                                        4 Apr 2022, 10:19

                                        @JeKK666
                                        man 2 poll:

                                        int poll(struct pollfd *fds, nfds_t nfds, int timeout);
                                        
                                           The timeout argument specifies the number of milliseconds that
                                        
                                           poll() should block waiting for a file descriptor to become
                                        
                                           ready.  The call will block until either:
                                        
                                        
                                        
                                           • a file descriptor becomes ready;
                                        
                                        
                                        
                                           • the call is interrupted by a signal handler; or
                                        
                                        
                                        
                                           • the timeout expires.
                                        

                                        You need to pass a timeout.

                                        I need it to block indefinetely until a HW interrupt occurs.

                                        If that were 100% true you would not be asking about how to interrupt the thread with isInterruptionRequested().

                                        J Offline
                                        J Offline
                                        JeKK666
                                        wrote on 4 Apr 2022, 10:28 last edited by
                                        #18

                                        @JonB i need to block indefinetely, unless a configuration changes, which will require changing how the sysfs endpoint are polled, and therefore run a slightly modified version of the thread code; i think my best option is going to be trying to throw a fake interrupt, so as to have the code react to isInterruptionRequested().

                                        Thanks everyone for the insights and suggestions :)

                                        Still haven't learned Lambdas...

                                        J 1 Reply Last reply 4 Apr 2022, 10:42
                                        0
                                        • J JonB
                                          4 Apr 2022, 10:20

                                          @KroMignon said in How to properly quit blocking thread:

                                          @JonB said in How to properly quit blocking thread:

                                          if your poll() is blocking as you said. [Yes the second avoids the quit() if no event loop, but not poll() blocking and failing to see isInterruptionRequested().]

                                          Using quit() don't make sense here. This thread do not have an event loop, so not signals/slots can be used here.

                                          Absolutely which is why I wrote what I did: your code is definitely better in that it does not attempt to use a useless quit(), but since the OP wants (thought he wanted) a blocking poll() call into the body it won't address that problem.

                                          K Offline
                                          K Offline
                                          KroMignon
                                          wrote on 4 Apr 2022, 10:28 last edited by
                                          #19

                                          @JonB said in How to properly quit blocking thread:

                                          Absolutely which is why I wrote what I did: your code is definitely better in that it does not attempt to use a useless quit(), but since the OP wants (thought he wanted) a blocking poll() call into the body it won't address that problem.

                                          I apologies, I read too quickly your post and misunderstood it, sorry for the noise!
                                          And yes, you are right, the poll() call definitively requires a timeout to ensure thread will exit loop without have to wait until a file event occurs.

                                          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
                                          • J JeKK666
                                            4 Apr 2022, 10:28

                                            @JonB i need to block indefinetely, unless a configuration changes, which will require changing how the sysfs endpoint are polled, and therefore run a slightly modified version of the thread code; i think my best option is going to be trying to throw a fake interrupt, so as to have the code react to isInterruptionRequested().

                                            Thanks everyone for the insights and suggestions :)

                                            J Offline
                                            J Offline
                                            JonB
                                            wrote on 4 Apr 2022, 10:42 last edited by
                                            #20

                                            @JeKK666 said in How to properly quit blocking thread:

                                            @JonB i need to block indefinetely, unless a configuration changes, which will require changing how the sysfs endpoint are polled, and therefore run a slightly modified version of the thread code; i think my best option is going to be trying to throw a fake interrupt, so as to have the code react to isInterruptionRequested().

                                            Indeed you can do it that way, raising a (Linux) signal() from the main thread to interrupt the poll() in the other thread. And if that is what you want or need to do, fine.

                                            However it is not unusual to write code which calls poll() with a timeout and then restart the poll if it timed out. Code like:

                                            void MyThread::run() {
                                                while(!isInterruptionRequested()) {
                                                    // do stuff here, including...
                                                    if (poll(..., timeout) != 0)
                                                    {
                                                         // genuine arrival of data, *not* timeout
                                                         // if timeout occurs, code goes through the `while` again
                                                         // which first checks for `isInterruptionRequested()` and then re starts a new `poll(..., timeout)`
                                                    }
                                                }    
                                            }
                                            

                                            per the doc's

                                            A return value of zero indicates that the system call timed out

                                            before any file descriptors became read.

                                            1 Reply Last reply
                                            1

                                            6/27

                                            4 Apr 2022, 09:42

                                            topic:navigator.unread, 21
                                            • Login

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