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().
Thanks everyone for the insights and suggestions :)
-
@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, thepoll()
call definitively requires a timeout to ensure thread will exit loop without have to wait until a file event occurs. -
@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 thepoll()
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 atimeout
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.
-
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 extraread()
andlseek(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()
-
@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()! -
@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! -
@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 ofpoll()
was due to timeout or real event, thread will see there's no useful info in this return ofpoll()
, 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?
-
@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 apoll()
with no further handling code, so that bit may be OK.In any case, if it is working for you that's fine!