views:

31

answers:

2

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.

+3  A: 

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.

Michael Burr
So how do I get the xsi / posix version?
Robert S. Barnes
+1  A: 

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.

Unknown
So how do I get the xsi / posix version?
Robert S. Barnes
I don't think you can prevent the g++ compiler from defining _GNU_SOURCE, so you might as well write your program to use that variant.
Unknown