Reputation: 431
Here I have some questions when using open in a multi-thread case with pthread_cancel()
. In the thread I need to open some files to read.
So my first question is that do I need to enclose the fields where I use those opened file descriptors with pthread_cleanup_push()
and pthread_cleanup_pop()
. I think if the thread is cancelled with the files still opened, it won't be good.
However, as far as I know, the open()
function itself is a possible cancellation point. And I don't know if the file descriptor is opened or not if a cancel happened there (or where can I get the information of that?)
At last, is there a Unix interface to tell if the file descriptor is opened or not?
Upvotes: 2
Views: 4152
Reputation: 140806
Yes, if a thread can be cancelled while it holds the only reference to open file descriptors, you need to use pthread_cleanup_push
/pop
to ensure they are closed; otherwise they will leak.
Indeed, the open
function itself is a cancellation point, as are several other resource allocation functions (here is a complete list of cancellation points). There is language in the standard that can be read to require the file not to have been opened yet if a cancel happens at an open
, but I do not trust implementations to have gotten that right. The only 100% reliable way to deal with this problem is to use pthread_setcancelstate
to disable cancellation while opening files (or allocating other resources), and reenable it only after the subsequent pthread_cleanup_push
.
You can tell whether a file descriptor is open by seeing whether a no-op fcntl
fails with errno set to EBADF
, but DO NOT DO THIS. It is intrinsically racey -- in between the check and the code control-dependent on the check, another thread may reuse that file descriptor number and your program will misbehave, possibly catastrophically (e.g. overwriting the wrong file).
Upvotes: 1
Reputation: 754890
Yes, using pthread_cleanup_push()
is a good idea.
If the thread is cancelled in open()
, the file descriptor won't be open so the cleanup code simply has to close anything that was opened previously.
You can use fstat()
to check if a file descriptor is open. Or you can use one of the other functions that take a file descriptor as an argument, looking for EBADF
(bad file descriptor) if the descriptor is not open). The advantage of fstat()
is that it is a pure interrogation function whereas most others try to change something about the descriptor. fcntl()
can do queries too.
Upvotes: 3