Check if a file that has been opened with fopen has been closed

ant2009 picture ant2009 · Jul 30, 2013 · Viewed 24.8k times · Source
gcc (GCC) 4.7.2
c89

Is it possible for check if a file has already closed?

I have opened a file using fopen() and closed using fclose(fd).

This file gets opened and closed during the running of the program. However, the user can terminate the program by doing a ctrl-c.

When I go to my cleanup routine, I don't know if the file is in a open or closed state. So if I try and do a fclose(fd) twice, it will stack dump.

Some ideas I have been throwing around:

  1. Add a state to the file to be either opened or closed, and then check that state, means more work for such a simple job.
  2. Don't do anything as the OS will cleanup automatially when the program ends.
  3. Is there is the access function, but that will just checks the mode.

Many thanks in advance,

Answer

nullptr picture nullptr · Jul 30, 2013

AFAIK, glibc doesn't provide a method to validate a FILE* variable.

Keeping some kind of state or just setting fd to NULL works, but you have to be careful not to get into your cleanup routine just after closing the file, but before resetting fd. As Ctrl+C sends a signal (SIGINT) to a program, you can just block the signal while the file is being closed and fd is being reset. So, your fclose in the main program should look like:

// 1. Block SIGINT
sigset_t old_mask, to_block;
sigemptyset(&to_block);
sigaddset(&to_block, SIGINT);
sigprocmask(SIG_BLOCK, &to_block, &old_mask);

// 2. Close the file and reset fd
fclose(fd);
fd = NULL;

// 3. Restore signal handling
sigprocmask(SIG_SETMASK, &old_mask, NULL);

And in your clean-up routine you should just check fd:

if (fd != NULL) fclose(fd);

If your program is multithreaded, you should use pthread_sigmask instead.

In your case, simple call of fcloseall() in the cleanup routine would be much easier.

As for the second option meant in your question, about doing nothing - well, the OS will clean-up everything for your program. Then only drawback is that if there were opened write streams, some data may be not written to disk. But maybe in case of Ctrl+C it's just ok.