What if close could fail?
Yesterday I made the claim that close() can’t fail in a meaningful way. Meaning that if it’s invoked on an object in a state that does not support close(), it’s a programming/coding error.
I believe that this is correct but we’ll see that there are challenges as a result of it.
Let’s explore briefly what might happen if it could fail for environmental factors. Are you going to write this code:
int main(int argc, const char *argv[]) {
for (int i=1; i<argc; i++) {
FILE *fp = fopen(argv[i], “w”);
if (fp == NULL) {
perror(“Unable to open file”);
exit(EXIT_FAILURE);
}
// This is how it should be written but nobody does... perror is somewhat lacking
if (fprintf(fp, “Hello there %s\n”, argv[i]) < 0) {
perror(“Unable to write to file”);
fclose(fp); // should this match how fclose() is called below?? probably.
exit(EXIT_FAILURE);
}
// controversial bit:
while (fclose(fp) == EOF) {
if (errno != ENOMEM) {
perror(“Unable to close file”);
exit(EXIT_FAILURE);
}
}
}
return EXIT_SUCCESS;
}
Maybe you should but I doubt it. Maybe we should also loop on EDEADLOCK also? ENOSPC? All errors? Probably not EBADF. This error code probably means that the file handle/id in the FILE is corrupt. Who’s going to document what?
My point here is only to try to put the nail in the coffin for resource management termination/close functions having public APIs that include failure modes other than invalid parameter.
[edited 5/3/05 2:11pm PST to fix missing return from main]
[edited 5/4/2001 4:00pm PST to fix missing close when fprintf() fails]
Comments
- Anonymous
May 03, 2005
Thanks for these articles. It has been a good series. Are you going to further discuss managing multple resources? - Anonymous
May 03, 2005
The comment has been removed - Anonymous
May 03, 2005
In that case dont you want to close the file if fprintf fails? ;-) - Anonymous
May 03, 2005
Actually I thought about doing that and maybe I should update the example (or provide a 2nd copy which includes that). My main point was to illustrate that if an API like close() can fail, you probably can't make forward progress until it does succeed and so you find yourself writing little loops all over the place retrying the operation.
Unfortunately the alternative is that the implementation of close() might itself have the loop (I'm planning on this being tomorrow's topic).
If figuring out how to write the call to close() is really this hard, there is no hope, so I have to conclude that clients have to just call close and it has to take care of business, whatever that means.