In the following code, I'm going to open a file and write something.
Because the program is run concurrently on multiple threads, the value log_fd after the fopen function finishes executing may be NULL.
Then, the program crashes and exits.
static void __log_prt__(const char *fmt, va_list ap)
{
// omitted code ...
FILE *log_fd = fopen(def_log_file, "a");
// omitted code ...
fclose(log_fd);
}
This will lead to errno 9: Bad file descriptor
I modified the program to loop through the fopen function until its return value is no longer NULL, just like the following code:
static void __log_prt__(const char *fmt, va_list ap)
{
// omitted code ...
FILE *log_fd = fopen(def_log_file, "a");
while (log_fd == NULL) {
log_fd = fopen(def_log_file, "a");
}
// omitted code ...
fclose(log_fd);
}
In this way, the program will no longer have crashes caused by errno 9.
Now I have a question, is this the right thing to do? Is there a more reasonable way?
FILE *log_fd = fopen(def_log_file, "a");
while (log_fd == NULL) {
log_fd = fopen(def_log_file, "a");
}
This approach seems very optimistic. From the man page, I counted around 42 different error conditions that could cause fopen ()
to fail.¹
If fopen ()
returns NULL
, there's no guarantee that recalling it will magically fix the conditions that caused it to fail in the first place.
Remember:
[1] — which includes ENOMEM
(Error No Memory), at which point you should be aborting.