summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changes/variadic_macros4
-rw-r--r--src/common/log.c96
-rw-r--r--src/common/torlog.h58
-rw-r--r--src/or/config.c6
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