Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

strerror_r returns trash when I manually set errno during testing

During testing I have a mock object which sets errno = ETIMEDOUT; The object I'm testing sees the error and calls strerror_r to get back an error string:

if (ret) {
    if (ret == EAI_SYSTEM) {
        char err[128];
        strerror_r(errno, err, 128);
        err_string.assign(err);
    } else {
        err_string.assign(gai_strerror(ret));
    }
    return ret;
}

I don't understand why strerror_r is returning trash. I even tried calling

strerror_r(ETIMEDOUT, err, 128)

directly and still got trash. I must be missing something. It seems I'm getting the gnu version of the function not the posix one, but that shouldn't make any difference in this case.

Edit

I'm on Ubuntu 8.04. glibc version looks like 2.7 in features.h.

like image 796
Robert S. Barnes Avatar asked Dec 09 '22 15:12

Robert S. Barnes


2 Answers

According to this page, http://linux.die.net/man/3/strerror_r, if you're using the GNU version of strerror_r(), the function might decide to not store anything at all into the buffer you provide; you'd need to use the string returned from the function (seems like a rather bizarre interface):

The GNU-specific strerror_r() returns a pointer to a string containing the error message. This may be either a pointer to a string that the function stores in buf, or a pointer to some (immutable) static string (in which case buf is unused). If the function stores a string in buf, then at most buflen bytes are stored (the string may be truncated if buflen is too small) and the string always includes a terminating null byte.

So if you happen to be using the GNU version you can't rely on your err buffer to have anything useful put into it, unless strerror_r() returns the address of err.

like image 123
Michael Burr Avatar answered Dec 12 '22 04:12

Michael Burr


The problem is that Linux has two strerror_r functions. If you read the manual,

   int strerror_r(int errnum, char *buf, size_t buflen);
               /* XSI-compliant */

   char *strerror_r(int errnum, char *buf, size_t buflen);
               /* GNU-specific */


The XSI-compliant version of strerror_r() is provided if:
       (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE

The g++ compiler automatically defines _GNU_SOURCE, so you are using the GNU version of the function which doesn't necessarily store a message in the buffer you provide.

like image 42
Unknown Avatar answered Dec 12 '22 03:12

Unknown