I have a thread running in the background that is reading events from an input device in a blocking fashion, now when I exit the application I want to clean up the thread properly, but I can't just run a pthread_join() because the thread would never exit due to the blocking IO.
How do I properly solve that situation? Should I send a pthread_kill(theard, SIGIO) or a pthread_kill(theard, SIGALRM) to break the block? Is either of that even the right signal? Or is there another way to solve this situation and let that child thread exit the blocking read?
Currently a bit puzzled since none of my googling turned up a solution.
This is on Linux and using pthreads.
Edit: I played around a bit with SIGIO and SIGALRM, when I don't install a signal handler they break the blocking IO up, but give a message on the console ("I/O possible") but when I install a signal handler, to avoid that message, they no longer break the blocking IO, so the thread doesn't terminate. So I am kind of back to step one.
A thread moves to the blocked state when it wants to access an object that is being used (locked) by another thread. Once that resource is available (unlocked) for the thread, it is no longer blocked and moves to the runnable state.
Yes, this can happen for any synchronization operation, where one thread needs to wait for another thread to do something.
It's completely possible to implement threads in user-space such that one thread can proceed while another thread block on I/O. The non-blocked thread should be able to send on the socket while the other thread is blocking on it (I've written such code).
The canonical way to do this is with pthread_cancel
, where the thread has done pthread_cleanup_push
/pop
to provide cleanup for any resources it is using.
Unfortunately this can NOT be used in C++ code, ever. Any C++ std lib code, or ANY try {} catch()
on the calling stack at the time of pthread_cancel
will potentially segvi killing your whole process.
The only workaround is to handle SIGUSR1
, setting a stop flag, pthread_kill(SIGUSR1)
, then anywhere the thread is blocked on I/O, if you get EINTR
check the stop flag before retrying the I/O. In practice, this does not always succeed on Linux, don't know why.
But in any case it's useless to talk about if you have to call any 3rd party lib, because they will most likely have a tight loop that simply restarts I/O on EINTR
. Reverse engineering their file descriptor to close it won't cut it either—they could be waiting on a semaphore or other resource. In this case, it is simply impossible to write working code, period. Yes, this is utterly brain-damaged. Talk to the guys who designed C++ exceptions and pthread_cancel
. Supposedly this may be fixed in some future version of C++. Good luck with that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With