Full_Name: Hallvard B Furuseth Version: HEAD, RE23, RE24 OS: URL: Submission from: (NULL) (129.240.6.233) Submitted by: hallvard
"grep -i strerror" shows some places <strerror/STRERROR>(errno) are passed to Debug(). However Debug() can evaluate its arguments twice: for -d output and syslog. Thus it can syslog the wrong message, since the -d stdio call can change errno.
Also strerror() can return NULL, which can break with Debug(%s). STRERROR() fixes that, but not the duplicate call. And strerror too can change errno:-( So the STRERROR() variant #elif defined( HAVE_STRERROR ) #define STRERROR(e) ( strerror(e) ? strerror(e) : _AC_ERRNO_UNKNOWN ) in include/ac/errno.h isn't quite safe either.
I suggest we put something like below in ac/string.h or ac/errno.h, then we can usually say if (whatever) { DEF_STRERROR(msg, errno); Debug(..., msg, ...); }
ac/something.h: #define DEF_STRERROR(msg, err) \ DECL_STRERROR(msg); \ SET_STRERROR(msg, err)
#ifdef HAVE_SYS_ERRLIST #define DECL_STRERROR(msg) \ unsigned int msg##_err_; \ const char *msg #define SET_STRERROR(msg, err) \ ((void)(msg = (msg##_err_ = (e)) < (unsigned) sys_nerr \ ? sys_errlist[msg##_err_] : _AC_ERRNO_UNKNOWN))
#elif <threaded> && defined( HAVE_NONPOSIX_STRERROR_R ) #define DECL_STRERROR(msg) \ char msg##_buf_[80]; \ const char *msg #define SET_STRERROR(msg, err) \ ((void) ((msg = strerror_r(err, msg##_buf_, 80)) || \ (msg = _AC_ERRNO_UNKNOWN)))
#elif <threaded> && defined( HAVE_STRERROR_R ) #define DECL_STRERROR(msg) \ char msg##_buf_[80]; \ const char *msg #define SET_STRERROR(msg, err) \ ((void) (msg = strerror_r(err, msg##_buf_, 80) != -1 \ ? msg##_buf_ : _AC_ERRNO_UNKNOWN))
#elif defined( HAVE_STRERROR ) #define DECL_STRERROR(msg) \ const char *msg #define SET_STRERROR(msg, err) \ ((void) ((msg = strerror(err)) || (msg = _AC_ERRNO_UNKNOWN)))
#else #define DECL_STRERROR(msg) const char *msg #define SET_STRERROR(msg, err) ((void) (msg = "Unknown error")) #endif
Don't know what the #if <threaded> test should look like, see ITS#5421.