From 8cb50703761affb496f2035768e0f024d9263938 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 15 Jul 2015 14:43:35 -0400 Subject: [PATCH] Use C99 variadic macros when not on GCC. 1) We already require C99. 2) This allows us to support MSVC again (thanks to Gisle Vanem for this part) 3) This change allows us to dump some rotten old compatibility code from log.c --- changes/variadic_macros | 4 ++ src/common/log.c | 96 +---------------------------------------- src/common/torlog.h | 56 +++++++++++++----------- src/or/config.c | 6 +++ 4 files changed, 42 insertions(+), 120 deletions(-) create mode 100644 changes/variadic_macros diff --git a/changes/variadic_macros b/changes/variadic_macros new file mode 100644 index 0000000000..0d84dd922e --- /dev/null +++ b/changes/variadic_macros @@ -0,0 +1,4 @@ + o Minor features (portability): + - Use C99 variadic macros when the compiler is not GCC. This avoids + failing compilations on MSVC, and fixes a log-file-based race + condition in our old workarounds. Original patch from Gisle Vanem. diff --git a/src/common/log.c b/src/common/log.c index 4ad0bc3697..e23691b6ab 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -674,9 +674,7 @@ tor_log_get_logfile_names(smartlist_t *out) UNLOCK_LOGS(); } -/** Output a message to the log, prefixed with a function name fn. */ -#ifdef __GNUC__ -/** GCC-based implementation of the log_fn backend, used when we have +/** Implementation of the log_fn backend, used when we have * variadic macros. All arguments are as for log_fn, except for * fn, which is the name of the calling functions. */ void @@ -706,98 +704,6 @@ log_fn_ratelim_(ratelim_t *ratelim, int severity, log_domain_mask_t domain, va_end(ap); tor_free(m); } -#else -/** @{ */ -/** Variant implementation of log_fn, log_debug, log_info,... for C compilers - * without variadic macros. In this case, the calling function sets - * log_fn_function_name_ to the name of the function, then invokes the - * appropriate log_fn_, log_debug_, etc. */ -const char *log_fn_function_name_=NULL; -void -log_fn_(int severity, log_domain_mask_t domain, const char *format, ...) -{ - va_list ap; - if (severity > log_global_min_severity_) - return; - va_start(ap,format); - logv(severity, domain, log_fn_function_name_, NULL, format, ap); - va_end(ap); - log_fn_function_name_ = NULL; -} -void -log_fn_ratelim_(ratelim_t *ratelim, int severity, log_domain_mask_t domain, - const char *format, ...) -{ - va_list ap; - char *m; - if (severity > log_global_min_severity_) - return; - m = rate_limit_log(ratelim, approx_time()); - if (m == NULL) - return; - va_start(ap, format); - logv(severity, domain, log_fn_function_name_, m, format, ap); - va_end(ap); - tor_free(m); -} -void -log_debug_(log_domain_mask_t domain, const char *format, ...) -{ - va_list ap; - /* For GCC we do this check in the macro. */ - if (PREDICT_LIKELY(LOG_DEBUG > log_global_min_severity_)) - return; - va_start(ap,format); - logv(LOG_DEBUG, domain, log_fn_function_name_, NULL, format, ap); - va_end(ap); - log_fn_function_name_ = NULL; -} -void -log_info_(log_domain_mask_t domain, const char *format, ...) -{ - va_list ap; - if (LOG_INFO > log_global_min_severity_) - return; - va_start(ap,format); - logv(LOG_INFO, domain, log_fn_function_name_, NULL, format, ap); - va_end(ap); - log_fn_function_name_ = NULL; -} -void -log_notice_(log_domain_mask_t domain, const char *format, ...) -{ - va_list ap; - if (LOG_NOTICE > log_global_min_severity_) - return; - va_start(ap,format); - logv(LOG_NOTICE, domain, log_fn_function_name_, NULL, format, ap); - va_end(ap); - log_fn_function_name_ = NULL; -} -void -log_warn_(log_domain_mask_t domain, const char *format, ...) -{ - va_list ap; - if (LOG_WARN > log_global_min_severity_) - return; - va_start(ap,format); - logv(LOG_WARN, domain, log_fn_function_name_, NULL, format, ap); - va_end(ap); - log_fn_function_name_ = NULL; -} -void -log_err_(log_domain_mask_t domain, const char *format, ...) -{ - va_list ap; - if (LOG_ERR > log_global_min_severity_) - return; - va_start(ap,format); - logv(LOG_ERR, domain, log_fn_function_name_, NULL, format, ap); - va_end(ap); - log_fn_function_name_ = NULL; -} -/** @} */ -#endif /** Free all storage held by victim. */ static void diff --git a/src/common/torlog.h b/src/common/torlog.h index 710313a9a6..45b2abfd7e 100644 --- a/src/common/torlog.h +++ b/src/common/torlog.h @@ -166,7 +166,6 @@ void tor_log_get_logfile_names(struct smartlist_t *out); extern int log_global_min_severity_; -#if defined(__GNUC__) || defined(RUNNING_DOXYGEN) void log_fn_(int severity, log_domain_mask_t domain, const char *funcname, const char *format, ...) CHECK_PRINTF(4,5); @@ -175,6 +174,12 @@ void log_fn_ratelim_(struct ratelim_t *ratelim, int severity, log_domain_mask_t domain, const char *funcname, const char *format, ...) CHECK_PRINTF(5,6); + +#if defined(__GNUC__) + +/* These are the GCC varidaic macros, so that older versions of GCC don't + * break. */ + /** Log a message at level severity, using a pretty-printed version * of the current function name. */ #define log_fn(severity, domain, args...) \ @@ -200,31 +205,32 @@ void log_fn_ratelim_(struct ratelim_t *ratelim, int severity, #else /* ! defined(__GNUC__) */ -void log_fn_(int severity, log_domain_mask_t domain, const char *format, ...); -struct ratelim_t; -void log_fn_ratelim_(struct ratelim_t *ratelim, int severity, - log_domain_mask_t domain, const char *format, ...); -void log_debug_(log_domain_mask_t domain, const char *format, ...); -void log_info_(log_domain_mask_t domain, const char *format, ...); -void log_notice_(log_domain_mask_t domain, const char *format, ...); -void log_warn_(log_domain_mask_t domain, const char *format, ...); -void log_err_(log_domain_mask_t domain, const char *format, ...); +/* Here are the c99 variadic macros, to work with non-GCC compilers */ -/* We don't have GCC's varargs macros, so use a global variable to pass the - * function name to log_fn */ -extern const char *log_fn_function_name_; -/* We abuse the comma operator here, since we can't use the standard - * do {...} while (0) trick to wrap this macro, since the macro can't take - * arguments. */ -#define log_fn (log_fn_function_name_=__func__),log_fn_ -#define log_fn_ratelim (log_fn_function_name_=__func__),log_fn_ratelim_ -#define log_debug (log_fn_function_name_=__func__),log_debug_ -#define log_info (log_fn_function_name_=__func__),log_info_ -#define log_notice (log_fn_function_name_=__func__),log_notice_ -#define log_warn (log_fn_function_name_=__func__),log_warn_ -#define log_err (log_fn_function_name_=__func__),log_err_ - -#endif /* !GNUC */ +#define log_debug(domain, args, ...) \ + STMT_BEGIN \ + if (PREDICT_UNLIKELY(log_global_min_severity_ == LOG_DEBUG)) \ + log_fn_(LOG_DEBUG, domain, __PRETTY_FUNCTION__, args, ##__VA_ARGS__); \ + STMT_END +#define log_info(domain, args,...) \ + log_fn_(LOG_INFO, domain, __PRETTY_FUNCTION__, args, ##__VA_ARGS__) +#define log_notice(domain, args,...) \ + log_fn_(LOG_NOTICE, domain, __PRETTY_FUNCTION__, args, ##__VA_ARGS__) +#define log_warn(domain, args,...) \ + log_fn_(LOG_WARN, domain, __PRETTY_FUNCTION__, args, ##__VA_ARGS__) +#define log_err(domain, args,...) \ + log_fn_(LOG_ERR, domain, __PRETTY_FUNCTION__, args, ##__VA_ARGS__) +/** Log a message at level severity, using a pretty-printed version + * of the current function name. */ +#define log_fn(severity, domain, args,...) \ + log_fn_(severity, domain, __PRETTY_FUNCTION__, args, ##__VA_ARGS__) +/** As log_fn, but use ratelim (an instance of ratelim_t) to control + * the frequency at which messages can appear. + */ +#define log_fn_ratelim(ratelim, severity, domain, args,...) \ + log_fn_ratelim_(ratelim, severity, domain, __PRETTY_FUNCTION__, \ + args, ##__VA_ARGS__) +#endif #ifdef LOG_PRIVATE MOCK_DECL(STATIC void, logv, (int severity, log_domain_mask_t domain, diff --git a/src/or/config.c b/src/or/config.c index 0d6c3003ff..bd74db6097 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -2583,8 +2583,14 @@ options_validate_cb(void *old_options, void *options, void *default_options, #define REJECT(arg) \ STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END +#ifdef __GNUC__ #define COMPLAIN(args...) \ STMT_BEGIN log_warn(LD_CONFIG, args); STMT_END +#else +#define COMPLAIN(args, ...) \ + STMT_BEGIN log_warn(LD_CONFIG, args, ##__VA_ARGS__); STMT_END +#endif + /** Log a warning message iff filepath is not absolute. * Warning message must contain option name option and