[Date Prev][Date Next] [Chronological] [Thread] [Top]

(ITS#5422) strerror(errno) problems



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.