cfflushuclibc

fflush() always returns 0 but sets errno to 11 (resource temporarily unavailable)


Whenever I call the vasprintf() function errno gets set to 11 (resource temporarily unavailable). However, it appears that everything is functioning correctly. To better understand the source of the error I found an implementation of vasprintf() in uclibc and put it in my program. What I found is that the fflush() is setting errno to 11. However, all indications are that the code is functioning correctly. For example, the return value from fflush() is 0. The size value for open_memstream() is updated correctly after the file is closed. The output buffer is updated correctly. I also called the output() function in an infinite loop to see if any memory was leaking, but I saw no increase in memory over a few thousand loops.

If the file was closed and the data was written, is there really an error to resolve?

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>

void output(int type, const char *fmt, ...)
{
    FILE *f;
    size_t size;
    int rv = -1;
    int fclose_return = 5;
    int fflush_return = 5;
    va_list ap;
    char *output_str_no_prefix = NULL;
    va_start(ap, fmt);
//  vasprintf(&output_str_no_prefix, fmt, ap);

    if ((f = open_memstream(&output_str_no_prefix, &size)) != NULL) {
        rv = vfprintf(f, fmt, ap);


        errno = 0;
        printf("%s: errno(%d): %s -- Return Value: %d\n",
                __func__, errno, strerror(errno), fflush_return);
        fflush_return = fflush(f);
        printf("%s: errno(%d): %s -- Return Value: %d\n",
                __func__, errno, strerror(errno), fflush_return);

        errno=0;
        fclose_return = fclose(f);
        printf("%s: errno(%d): %s -- Return Value: %d\n",
                __func__, errno, strerror(errno), fclose_return);

        if (rv < 0) {
            free(output_str_no_prefix);
            output_str_no_prefix = NULL;
        } else {
            output_str_no_prefix = realloc(output_str_no_prefix, rv + 1);
        }
    }
    va_end(ap);
    printf ("%s\n", output_str_no_prefix);
    free(output_str_no_prefix);
}

int main () {
    output(0, "Hello! -- %d\n", 4);
    return 0;

}

Here is the output for the program above.

# /data/HelloWorld
output: errno(0): Success -- Return Value: 5
output: errno(11): Resource temporarily unavailable -- Return Value: 0
output: errno(0): Success -- Return Value: 0
Hello! -- 4

#

Solution

  • This is a subtlety of the C standard. Most library functions are allowed to set errno to a nonzero value even if they succeed. You should only look at errno after a function has already reported failure in some other way.

    Two important notes:

    Standardese: N1570 section 7.5 paragraph 3

    The value of errno in the initial thread is zero at program startup (the initial value of errno in other threads is an indeterminate value), but is never set to zero by any library function. The value of errno may be set to nonzero by a library function call whether or not there is an error, provided [the documentation for the specific function doesn't say otherwise].