Yan  Li
Yan Li

Reputation: 431

How to know if a file descriptor is opened?

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

Answers (2)

zwol
zwol

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

Jonathan Leffler
Jonathan Leffler

Reputation: 754890

  1. Yes, using pthread_cleanup_push() is a good idea.

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

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

Related Questions