Search code examples
cfopenerrno

Run a C program in CentOS7, what should I do if I encounter errno 9 (Bad file descriptor)?


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?


Solution

  • 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:

    • Failure is always an option.
    • Fail fast, fail early, and fail often.
    • And do not trade safety for anything.

    [1] — which includes ENOMEM (Error No Memory), at which point you should be aborting.