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

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.
  • JonBJ JonB

    @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!

    JeKK666J Offline
    JeKK666J Offline
    JeKK666
    wrote on 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
    • JeKK666J JeKK666

      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

      KroMignonK Offline
      KroMignonK Offline
      KroMignon
      wrote on last edited by KroMignon
      #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)

      JeKK666J 1 Reply Last reply
      1
      • JeKK666J JeKK666

        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.HilkJ Offline
        J.HilkJ Offline
        J.Hilk
        Moderators
        wrote on 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
        • KroMignonK KroMignon

          @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
              }    
          }
          
          JeKK666J Offline
          JeKK666J Offline
          JeKK666
          wrote on 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...

          JonBJ 1 Reply Last reply
          0
          • jsulmJ jsulm

            @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.

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on 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?

            JeKK666J 1 Reply Last reply
            0
            • JeKK666J JeKK666

              @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

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by JonB
              #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().]

              JeKK666J KroMignonK 2 Replies Last reply
              1
              • JonBJ JonB

                @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().]

                JeKK666J Offline
                JeKK666J Offline
                JeKK666
                wrote on last edited by
                #13

                @JonB yikes... that's right

                Still haven't learned Lambdas...

                1 Reply Last reply
                0
                • JonBJ JonB

                  @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?

                  JeKK666J Offline
                  JeKK666J Offline
                  JeKK666
                  wrote on 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...

                  JonBJ 1 Reply Last reply
                  0
                  • JonBJ JonB

                    @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().]

                    KroMignonK Offline
                    KroMignonK Offline
                    KroMignon
                    wrote on 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)

                    JonBJ 1 Reply Last reply
                    0
                    • JeKK666J JeKK666

                      @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.

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by JonB
                      #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().

                      JeKK666J 1 Reply Last reply
                      2
                      • KroMignonK KroMignon

                        @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.

                        JonBJ Offline
                        JonBJ Offline
                        JonB
                        wrote on last edited by JonB
                        #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.

                        KroMignonK 1 Reply Last reply
                        1
                        • JonBJ JonB

                          @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().

                          JeKK666J Offline
                          JeKK666J Offline
                          JeKK666
                          wrote on 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...

                          JonBJ 1 Reply Last reply
                          0
                          • JonBJ JonB

                            @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.

                            KroMignonK Offline
                            KroMignonK Offline
                            KroMignon
                            wrote on 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
                            • JeKK666J JeKK666

                              @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 :)

                              JonBJ Offline
                              JonBJ Offline
                              JonB
                              wrote on 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
                              • JeKK666J Offline
                                JeKK666J Offline
                                JeKK666
                                wrote on last edited by JeKK666
                                #21

                                After some testing, i was able to conclude that for my specific use case the sequence

                                t.terminate();
                                t.wait();
                                

                                does not carry any evident drawback.
                                Perhaps it'll show its limits with time, in the form of some undebuggable issues, but i think it will be fine.... Probably.

                                My greatest concern was for the file descriptors upon which poll() is invoked, but i figured that if they are opened in the constructor of class MyThread, and not closed upon termination of thread t, and t is not deleted since it's immediately restated with the new config when needed, then i could just perform an extra read() and lseek(fd, 0, SEEK_SET) upon thread start to put the cursor in the correct place and clear the interrupt flag of the sysfs endpoint.

                                Also to note, there should be no possibility of terminating the thread when poll() is returning and the content of the file is being read, due to how the physical system works.

                                Thanks @JonB for the pointing me to (Linux) signal()

                                Still haven't learned Lambdas...

                                jsulmJ JonBJ 2 Replies Last reply
                                0
                                • JeKK666J JeKK666

                                  After some testing, i was able to conclude that for my specific use case the sequence

                                  t.terminate();
                                  t.wait();
                                  

                                  does not carry any evident drawback.
                                  Perhaps it'll show its limits with time, in the form of some undebuggable issues, but i think it will be fine.... Probably.

                                  My greatest concern was for the file descriptors upon which poll() is invoked, but i figured that if they are opened in the constructor of class MyThread, and not closed upon termination of thread t, and t is not deleted since it's immediately restated with the new config when needed, then i could just perform an extra read() and lseek(fd, 0, SEEK_SET) upon thread start to put the cursor in the correct place and clear the interrupt flag of the sysfs endpoint.

                                  Also to note, there should be no possibility of terminating the thread when poll() is returning and the content of the file is being read, due to how the physical system works.

                                  Thanks @JonB for the pointing me to (Linux) signal()

                                  jsulmJ Online
                                  jsulmJ Online
                                  jsulm
                                  Lifetime Qt Champion
                                  wrote on last edited by
                                  #22

                                  @JeKK666 said in How to properly quit blocking thread:

                                  but i figured that if they are opened in the constructor of class MyThread

                                  Keep in mind that only what you create inside run() will belong to the new thread!
                                  What you create inside MyThread constructor will belong to the thread creating MyThread instance.
                                  So, all variables you need to be in the thread should be created inside run()!

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

                                  JeKK666J 1 Reply Last reply
                                  3
                                  • JeKK666J JeKK666

                                    After some testing, i was able to conclude that for my specific use case the sequence

                                    t.terminate();
                                    t.wait();
                                    

                                    does not carry any evident drawback.
                                    Perhaps it'll show its limits with time, in the form of some undebuggable issues, but i think it will be fine.... Probably.

                                    My greatest concern was for the file descriptors upon which poll() is invoked, but i figured that if they are opened in the constructor of class MyThread, and not closed upon termination of thread t, and t is not deleted since it's immediately restated with the new config when needed, then i could just perform an extra read() and lseek(fd, 0, SEEK_SET) upon thread start to put the cursor in the correct place and clear the interrupt flag of the sysfs endpoint.

                                    Also to note, there should be no possibility of terminating the thread when poll() is returning and the content of the file is being read, due to how the physical system works.

                                    Thanks @JonB for the pointing me to (Linux) signal()

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

                                    @JeKK666 said in How to properly quit blocking thread:

                                    Thanks @JonB for the pointing me to (Linux) signal()

                                    You are welcome, but I don't understand why you chose that route rather than the simpler/safer repeated poll() with timeout as per the code I posted earlier. Maybe you have a reason, or maybe I won't understand!

                                    JeKK666J 1 Reply Last reply
                                    0
                                    • JonBJ JonB

                                      @JeKK666 said in How to properly quit blocking thread:

                                      Thanks @JonB for the pointing me to (Linux) signal()

                                      You are welcome, but I don't understand why you chose that route rather than the simpler/safer repeated poll() with timeout as per the code I posted earlier. Maybe you have a reason, or maybe I won't understand!

                                      JeKK666J Offline
                                      JeKK666J Offline
                                      JeKK666
                                      wrote on last edited by
                                      #24

                                      @JonB it might be just down to microcontroller heritage, working with a very resource constrained system, keeping the ISR code short and avoiding all unnecessary triggers of it.

                                      My reasoning: if the poll() in the thread times out, the thread will have to be switched in context first, a compare will have to be executed to check whether the return of poll() was due to timeout or real event, thread will see there's no useful info in this return of poll(), it will then need to restart the polling with another scheduled timeout and then switch out of context to resume execution of the main thread.
                                      All this happens while i already know that the information triggering the chain of events is invalid, i.e. a timeout: the information i seek is not the content of the file I'm polling, but the return event itself.

                                      Therefore i concluded that the whole ordeal would be a pointless waste of resources, moreover skippable altogether.

                                      Next problem faced was "i need to change the way i look for interrupt, before the next interrupt occurs" as detailed before, and the question i came to the forum for help with 😊

                                      Hope this sounds reasonable, can i hear your thoughts about this?

                                      Still haven't learned Lambdas...

                                      JonBJ 1 Reply Last reply
                                      0
                                      • jsulmJ jsulm

                                        @JeKK666 said in How to properly quit blocking thread:

                                        but i figured that if they are opened in the constructor of class MyThread

                                        Keep in mind that only what you create inside run() will belong to the new thread!
                                        What you create inside MyThread constructor will belong to the thread creating MyThread instance.
                                        So, all variables you need to be in the thread should be created inside run()!

                                        JeKK666J Offline
                                        JeKK666J Offline
                                        JeKK666
                                        wrote on last edited by
                                        #25

                                        @jsulm this i might not have given the proper consideration to... Thanks, I'll look into it further 👍🏻

                                        Still haven't learned Lambdas...

                                        1 Reply Last reply
                                        0
                                        • JeKK666J JeKK666

                                          @JonB it might be just down to microcontroller heritage, working with a very resource constrained system, keeping the ISR code short and avoiding all unnecessary triggers of it.

                                          My reasoning: if the poll() in the thread times out, the thread will have to be switched in context first, a compare will have to be executed to check whether the return of poll() was due to timeout or real event, thread will see there's no useful info in this return of poll(), it will then need to restart the polling with another scheduled timeout and then switch out of context to resume execution of the main thread.
                                          All this happens while i already know that the information triggering the chain of events is invalid, i.e. a timeout: the information i seek is not the content of the file I'm polling, but the return event itself.

                                          Therefore i concluded that the whole ordeal would be a pointless waste of resources, moreover skippable altogether.

                                          Next problem faced was "i need to change the way i look for interrupt, before the next interrupt occurs" as detailed before, and the question i came to the forum for help with 😊

                                          Hope this sounds reasonable, can i hear your thoughts about this?

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

                                          @JeKK666
                                          As I said, you may (well) have your reasons which I probably won't understand, I wouldn't know a "microcontroller" if it hit me in the face! :)

                                          Be aware that when you do call Linux signal() there is quite a bit of overhead involved during its execution. You also have to be careful to know just what it interrupts, what state you are left in, and you are not supposed to do very much code in any signal handler you might have --- however here I think you are just using it to interrupt a poll() with no further handling code, so that bit may be OK.

                                          In any case, if it is working for you that's fine!

                                          JeKK666J 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