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.