aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2008-01-02 05:38:53 +0000
committerNick Mathewson <nickm@torproject.org>2008-01-02 05:38:53 +0000
commitc0ec2815652842bdb2b533c2a8ddd125f26730fb (patch)
treee78f5db19a5bbb0634b39a0ad8172d6cd4029795
parentfeb1c60e9d4cf6f3f17feabd7278ace97c5fd3ed (diff)
downloadtor-c0ec2815652842bdb2b533c2a8ddd125f26730fb.tar
tor-c0ec2815652842bdb2b533c2a8ddd125f26730fb.tar.gz
r15784@tombo: nickm | 2008-01-02 00:38:06 -0500
Fix bug 575: protect the list of logs with a mutex. I couldn't find any appreciable change in logging performance on osx, but ymmv. You can undef USE_LOG_MUTEX to see if stuff gets faster for you. svn:r13019
-rw-r--r--ChangeLog5
-rw-r--r--src/common/log.c110
-rw-r--r--src/common/log.h1
-rw-r--r--src/or/main.c1
-rw-r--r--src/or/test.c2
5 files changed, 102 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index f4cb19e11..f763836f1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -9,11 +9,16 @@ Changes in version 0.2.0.16-alpha - 2008-01-??
o Minor performance improvements:
- Reference-count and share copies of address policy entries; only
5% of them were actually distinct.
+ - Never walk through the list of logs if we know that no log is
+ interested in a given message.
o Minor bugfixes:
- When an authority has not signed a consensus, do not try to
download a nonexistant "certificate with key 00000000". Bugfix
on 0.2.0.x. Fixes bug 569.
+ - Use a mutex to protect the list of logs, so we never write to
+ the list as it's being freed. Bugfix on 0.1.2.x. Fixes the
+ very rare bug 575, which is kind of the revenge of bug 222.
o Minor features (controller):
- Get NS events working again. (Patch from tup)
diff --git a/src/common/log.c b/src/common/log.c
index 147c2d18e..72dff4ae5 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -78,14 +78,28 @@ should_log_function_name(uint32_t domain, int severity)
}
}
-/* XXXX We should really have this protected by a mutex or something;
- * XXXX see bug 222. */
+#define USE_LOG_MUTEX
+
+#ifdef USE_LOG_MUTEX
+/** A mutex to guard changes to logfiles and logging. */
+static tor_mutex_t *log_mutex = NULL;
+#endif
/** Linked list of logfile_t. */
static logfile_t *logfiles = NULL;
#ifdef HAVE_SYSLOG_H
static int syslog_count = 0;
#endif
+#ifdef USE_LOG_MUTEX
+#define LOCK_LOGS() STMT_BEGIN \
+ tor_mutex_acquire(log_mutex); \
+ STMT_END
+#define UNLOCK_LOGS() STMT_BEGIN tor_mutex_release(log_mutex); STMT_END
+#else
+#define LOCK_LOGS() STMT_NIL
+#define UNLOCK_LOGS() STMT_NIL
+#endif
+
/* What's the lowest log level anybody cares about? */
int _log_global_min_severity = LOG_NOTICE;
@@ -241,6 +255,7 @@ logv(int severity, uint32_t domain, const char *funcname, const char *format,
char *end_of_prefix=NULL;
assert(format);
+ LOCK_LOGS();
lf = logfiles;
while (lf) {
if (severity > lf->min_loglevel || severity < lf->max_loglevel) {
@@ -282,6 +297,7 @@ logv(int severity, uint32_t domain, const char *funcname, const char *format,
}
lf = lf->next;
}
+ UNLOCK_LOGS();
}
/** Output a message to the log. */
@@ -289,6 +305,8 @@ void
_log(int severity, uint32_t domain, const char *format, ...)
{
va_list ap;
+ if (severity > _log_global_min_severity)
+ return;
va_start(ap,format);
logv(severity, domain, NULL, format, ap);
va_end(ap);
@@ -300,6 +318,8 @@ void
_log_fn(int severity, uint32_t domain, const char *fn, const char *format, ...)
{
va_list ap;
+ if (severity > _log_global_min_severity)
+ return;
va_start(ap,format);
logv(severity, domain, fn, format, ap);
va_end(ap);
@@ -310,6 +330,8 @@ void
_log_fn(int severity, uint32_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, format, ap);
va_end(ap);
@@ -319,6 +341,9 @@ void
_log_debug(uint32_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, format, ap);
va_end(ap);
@@ -328,6 +353,8 @@ void
_log_info(uint32_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, format, ap);
va_end(ap);
@@ -337,6 +364,8 @@ void
_log_notice(uint32_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, format, ap);
va_end(ap);
@@ -346,6 +375,8 @@ void
_log_warn(uint32_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, format, ap);
va_end(ap);
@@ -355,6 +386,8 @@ void
_log_err(uint32_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, format, ap);
va_end(ap);
@@ -367,8 +400,10 @@ void
logs_free_all(void)
{
logfile_t *victim, *next;
+ LOCK_LOGS();
next = logfiles;
logfiles = NULL;
+ UNLOCK_LOGS();
while (next) {
victim = next;
next = next->next;
@@ -423,10 +458,10 @@ close_log(logfile_t *victim)
}
/** Add a log handler to send all messages of severity <b>loglevel</b>
- * or higher to <b>stream</b>. */
-void
-add_stream_log(int loglevelMin, int loglevelMax,
- const char *name, FILE *stream)
+ * or higher to <b>stream</b>. DOCDOC.*/
+static void
+add_stream_log_impl(int loglevelMin, int loglevelMax,
+ const char *name, FILE *stream)
{
logfile_t *lf;
lf = tor_malloc_zero(sizeof(logfile_t));
@@ -435,21 +470,40 @@ add_stream_log(int loglevelMin, int loglevelMax,
lf->max_loglevel = loglevelMax;
lf->file = stream;
lf->next = logfiles;
- logfiles = lf;
+ logfiles = lf;
_log_global_min_severity = get_min_log_level();
}
+/** Add a log handler to send all messages of severity <b>loglevel</b>
+ * or higher to <b>stream</b>. */
+void
+add_stream_log(int loglevelMin, int loglevelMax,
+ const char *name, FILE *stream)
+{
+ LOCK_LOGS();
+ add_stream_log_impl(loglevelMin, loglevelMax, name, stream);
+ UNLOCK_LOGS();
+}
+
+/** Initialize the global logging facility */
+void
+init_logging(void)
+{
+ if (!log_mutex)
+ log_mutex = tor_mutex_new();
+}
+
/** Add a log handler to receive messages during startup (before the real
* logs are initialized).
*/
void
add_temp_log(void)
{
- add_stream_log(LOG_NOTICE, LOG_ERR, "<temp>", stdout);
+ LOCK_LOGS();
+ add_stream_log_impl(LOG_NOTICE, LOG_ERR, "<temp>", stdout);
logfiles->is_temporary = 1;
-
- _log_global_min_severity = get_min_log_level();
+ UNLOCK_LOGS();
}
/**
@@ -467,9 +521,11 @@ add_callback_log(int loglevelMin, int loglevelMax, log_callback cb)
lf->filename = tor_strdup("<callback>");
lf->callback = cb;
lf->next = logfiles;
- logfiles = lf;
+ LOCK_LOGS();
+ logfiles = lf;
_log_global_min_severity = get_min_log_level();
+ UNLOCK_LOGS();
return 0;
}
@@ -480,14 +536,15 @@ change_callback_log_severity(int loglevelMin, int loglevelMax,
log_callback cb)
{
logfile_t *lf;
+ LOCK_LOGS();
for (lf = logfiles; lf; lf = lf->next) {
if (lf->callback == cb) {
lf->min_loglevel = loglevelMin;
lf->max_loglevel = loglevelMax;
}
}
-
_log_global_min_severity = get_min_log_level();
+ UNLOCK_LOGS();
}
/** Close any log handlers added by add_temp_log or marked by mark_logs_temp */
@@ -495,6 +552,8 @@ void
close_temp_logs(void)
{
logfile_t *lf, **p;
+
+ LOCK_LOGS();
for (p = &logfiles; *p; ) {
if ((*p)->is_temporary) {
lf = *p;
@@ -509,6 +568,7 @@ close_temp_logs(void)
}
_log_global_min_severity = get_min_log_level();
+ UNLOCK_LOGS();
}
/** Make all currently temporary logs (set to be closed by close_temp_logs)
@@ -517,8 +577,10 @@ void
rollback_log_changes(void)
{
logfile_t *lf;
+ LOCK_LOGS();
for (lf = logfiles; lf; lf = lf->next)
lf->is_temporary = ! lf->is_temporary;
+ UNLOCK_LOGS();
close_temp_logs();
}
@@ -527,8 +589,10 @@ void
mark_logs_temp(void)
{
logfile_t *lf;
+ LOCK_LOGS();
for (lf = logfiles; lf; lf = lf->next)
lf->is_temporary = 1;
+ UNLOCK_LOGS();
}
/**
@@ -540,14 +604,22 @@ int
add_file_log(int loglevelMin, int loglevelMax, const char *filename)
{
FILE *f;
+ logfile_t *lf;
f = fopen(filename, "a");
if (!f) return -1;
- add_stream_log(loglevelMin, loglevelMax, filename, f);
+ LOCK_LOGS();
+ add_stream_log_impl(loglevelMin, loglevelMax, filename, f);
logfiles->needs_close = 1;
- if (log_tor_version(logfiles, 0) < 0) {
- delete_log(logfiles);
- }
+ lf = logfiles;
_log_global_min_severity = get_min_log_level();
+ UNLOCK_LOGS();
+
+ if (log_tor_version(lf, 0) < 0) {
+ LOCK_LOGS();
+ delete_log(lf);
+ UNLOCK_LOGS();
+ }
+
return 0;
}
@@ -568,10 +640,12 @@ add_syslog_log(int loglevelMin, int loglevelMax)
lf->filename = tor_strdup("<syslog>");
lf->max_loglevel = loglevelMax;
lf->is_syslog = 1;
+
+ LOCK_LOGS();
lf->next = logfiles;
logfiles = lf;
-
_log_global_min_severity = get_min_log_level();
+ UNLOCK_LOGS();
return 0;
}
#endif
@@ -619,9 +693,11 @@ void
switch_logs_debug(void)
{
logfile_t *lf;
+ LOCK_LOGS();
for (lf = logfiles; lf; lf=lf->next) {
lf->min_loglevel = LOG_DEBUG;
}
+ UNLOCK_LOGS();
}
#ifdef HAVE_EVENT_SET_LOG_CALLBACK
diff --git a/src/common/log.h b/src/common/log.h
index d2693744b..6c86dd378 100644
--- a/src/common/log.h
+++ b/src/common/log.h
@@ -94,6 +94,7 @@
/** Callback type used for add_callback_log. */
typedef void (*log_callback)(int severity, uint32_t domain, const char *msg);
+void init_logging(void);
int parse_log_level(const char *level);
const char *log_level_to_string(int level);
void add_stream_log(int severityMin, int severityMax, const char *name,
diff --git a/src/or/main.c b/src/or/main.c
index c9ac54dc8..22c3175e6 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -1945,6 +1945,7 @@ tor_main(int argc, char *argv[])
_tor_dmalloc_free);
log_notice(LD_CONFIG, "Set up dmalloc; returned %d", r);
#endif
+ init_logging();
#ifdef NT_SERVICE
{
int done = 0;
diff --git a/src/or/test.c b/src/or/test.c
index fed412816..23bae4820 100644
--- a/src/or/test.c
+++ b/src/or/test.c
@@ -3504,6 +3504,8 @@ main(int c, char**v)
int verbose = 0, any_selected = 0;
int loglevel = LOG_ERR;
+ init_logging();
+
for (i = 1; i < c; ++i) {
if (!strcmp(v[i], "-v") || !strcmp(v[i], "--verbose"))
verbose++;