diff options
-rw-r--r-- | changes/variadic_macros | 4 | ||||
-rw-r--r-- | src/common/log.c | 96 | ||||
-rw-r--r-- | src/common/torlog.h | 58 | ||||
-rw-r--r-- | src/or/config.c | 6 |
4 files changed, 43 insertions, 121 deletions
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 <b>fn</b>. */ -#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 * <b>fn</b>, 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 <b>victim</b>. */ 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 <b>severity</b>, 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, ...); - -/* 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 */ +/* Here are the c99 variadic macros, to work with non-GCC compilers */ + +#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 <b>severity</b>, 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 <b>ratelim</b> (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 <b>filepath</b> is not absolute. * Warning message must contain option name <b>option</b> and |