问题
I am reading in a blocked way from a device/filedescriptor. It might happen, that in a different thread the device is closed and filedescriptor is deleted. Unfortunatly the read doesn't return or take notice and keeps blocking.
As a workaround I could do a while loop with select as a timeout. If a timeout happens, I can check the filedescriptor and in case it is gone not calling read but return.
I am wondering, if there is a better way in Linux-C ?
回答1:
The code you are describing has an inherent race condition - if another thread could be a in blocking read()
on a file descriptor when you close()
that file descriptor, the other thread could just as well be just about to call read()
instead.
You can't call close()
unless you know that all other threads are no longer in a position to be using that file descriptor at all.
The easiest way to handle cases like you describe is for one thread to be the 'owning' thread of each file descriptor, that is responsible for closing the file descriptor. Other threads don't directly close it - instead they mark the file descriptor as "to be closed" in some shared data structure and wake up the owning thread.
You can make it possible to wake the owning thread by having it not block in read()
but instead block in select()
or poll()
with another file descriptor - usually a pipe - in the set as well as the target file descriptor. The thread is woken by writing to the other end of that pipe.
回答2:
Once a file descriptor is closed by other thread, it's not easy to verify it happened. What if other thread re-opened a file and got the same
file descriptor? On a successful close()
call, you can't access the file descriptor again and it'll be undefined. On a failed close()
call, POSIX leaves the state of the file descriptor unspecified.
The select()
option suffers from the same as described above.
Your problem is not really anything different to any other data race issue in a multi-threaded program. I suggest you re-write the code so that threads don't access the file descriptor without synchronization. Or, avoid multiple threads reading from the same file descriptor if that's possible.
来源:https://stackoverflow.com/questions/40301754/c-blocking-read-should-return-if-filedescriptor-is-deleted