How can I check to see if a file descriptor was closed?

user2931210 picture user2931210 · Oct 29, 2013 · Viewed 13k times · Source

In a POSIX environment when using system calls to manipulate text files (open(), close(), read(), write()), is there a way to to check to see if I actually closed a file descriptor when using close(file_descriptor)?

Example:

int main(int argc, char **argv)
{
    int input_file; // file descriptor for input file
    int output_file; // file descriptor for output file
    input_file = open(argv[1], O_RDONLY));
    ouput_file = open(argv[2], ...file properties & permissions and crap.....);

    // blah blah blah...

    close(input_file);
    close(output_file);

    // what can I code here to check if the file descriptor was actually closed?
}

Answer

Sergey L. picture Sergey L. · Oct 29, 2013

The easiest way is probably to just check the return value of your first close.

if (close(input_file)) {
    perror("close");
} else {
    // all good
}

This is the only thread-safe way. In a multi-threaded program, another thread could get a new file descriptor that recycles the fd number of the one that was just closed.


In single-threaded code only, where nothing can recycle an fd between close and check:

If you wish to check whether a file descriptor is valid afterwards then you can use any function that consumes a file descriptor and check it's error code. The most non-intervening and light weight is probably fcntl/F_GETFL

if (fcntl(fd, F_GETFL) < 0 && errno == EBADF) {
    // file descriptor is invalid or closed
}

You could also just call close a second time and it can also fail with EBADF.

if (close(fd) && errno == EBADF) {
    // file descriptor is invalid or closed
} else {
    // we successfully closed fd *now* (e.g. first close failed with EINTR)
    // or there was a different error
}

close doesn't modify errno on success, but we only read errno when close returns non-zero, meaning it has been set.