aboutsummaryrefslogtreecommitdiff
path: root/src/common/log.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/log.c')
-rw-r--r--src/common/log.c153
1 files changed, 80 insertions, 73 deletions
diff --git a/src/common/log.c b/src/common/log.c
index fe93bd7f57..2fef2cc5d9 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -33,11 +33,9 @@
#include "compat.h"
#include "util.h"
#define LOG_PRIVATE
-#include "log.h"
+#include "torlog.h"
#include "container.h"
-#include <event.h>
-
#define TRUNCATED_STR "[...truncated]"
#define TRUNCATED_STR_LEN 14
@@ -83,7 +81,7 @@ should_log_function_name(log_domain_mask_t domain, int severity)
/* All debugging messages occur in interesting places. */
return 1;
case LOG_NOTICE:
- case LOG_WARN:
+ case LOG_WARN:
case LOG_ERR:
/* We care about places where bugs occur. */
return (domain == LD_BUG);
@@ -105,6 +103,17 @@ static logfile_t *logfiles = NULL;
static int syslog_count = 0;
#endif
+/** Represents a log message that we are going to send to callback-driven
+ * loggers once we can do so in a non-reentrant way. */
+typedef struct pending_cb_message_t {
+ int severity;
+ log_domain_mask_t domain;
+ char *msg;
+} pending_cb_message_t;
+
+/** Log messages waiting to be replayed onto callback-based logs */
+static smartlist_t *pending_cb_messages = NULL;
+
#define LOCK_LOGS() STMT_BEGIN \
tor_mutex_acquire(&log_mutex); \
STMT_END
@@ -263,6 +272,7 @@ logv(int severity, log_domain_mask_t domain, const char *funcname,
int formatted = 0;
logfile_t *lf;
char *end_of_prefix=NULL;
+ int callbacks_deferred = 0;
/* Call assert, not tor_assert, since tor_assert calls log on failure. */
assert(format);
@@ -270,6 +280,10 @@ logv(int severity, log_domain_mask_t domain, const char *funcname,
* interesting and hard to diagnose effects */
assert(severity >= LOG_ERR && severity <= LOG_DEBUG);
LOCK_LOGS();
+
+ if ((! (domain & LD_NOCB)) && smartlist_len(pending_cb_messages))
+ flush_pending_log_callbacks();
+
lf = logfiles;
while (lf) {
if (! (lf->severities->masks[SEVERITY_MASK_IDX(severity)] & domain)) {
@@ -280,10 +294,6 @@ logv(int severity, log_domain_mask_t domain, const char *funcname,
lf = lf->next;
continue;
}
- if (lf->callback && (domain & LD_NOCB)) {
- lf = lf->next;
- continue;
- }
if (lf->seems_dead) {
lf = lf->next;
continue;
@@ -318,7 +328,19 @@ logv(int severity, log_domain_mask_t domain, const char *funcname,
lf = lf->next;
continue;
} else if (lf->callback) {
- lf->callback(severity, domain, end_of_prefix);
+ if (domain & LD_NOCB) {
+ if (!callbacks_deferred) {
+ pending_cb_message_t *msg = tor_malloc(sizeof(pending_cb_message_t));
+ msg->severity = severity;
+ msg->domain = domain;
+ msg->msg = tor_strdup(end_of_prefix);
+ smartlist_add(pending_cb_messages, msg);
+
+ callbacks_deferred = 1;
+ }
+ } else {
+ lf->callback(severity, domain, end_of_prefix);
+ }
lf = lf->next;
continue;
}
@@ -334,7 +356,7 @@ logv(int severity, log_domain_mask_t domain, const char *funcname,
/** Output a message to the log. */
void
-_log(int severity, log_domain_mask_t domain, const char *format, ...)
+tor_log(int severity, log_domain_mask_t domain, const char *format, ...)
{
va_list ap;
if (severity > _log_global_min_severity)
@@ -432,6 +454,8 @@ _log_err(log_domain_mask_t domain, const char *format, ...)
static void
log_free(logfile_t *victim)
{
+ if (!victim)
+ return;
tor_free(victim->severities);
tor_free(victim->filename);
tor_free(victim);
@@ -555,6 +579,8 @@ init_logging(void)
tor_mutex_init(&log_mutex);
log_mutex_initialized = 1;
}
+ if (pending_cb_messages == NULL)
+ pending_cb_messages = smartlist_create();
}
/** Add a log handler to receive messages during startup (before the real
@@ -613,6 +639,48 @@ change_callback_log_severity(int loglevelMin, int loglevelMax,
UNLOCK_LOGS();
}
+/** If there are any log messages that were genered with LD_NOCB waiting to
+ * be sent to callback-based loggers, send them now. */
+void
+flush_pending_log_callbacks(void)
+{
+ logfile_t *lf;
+ smartlist_t *messages, *messages_tmp;
+
+ LOCK_LOGS();
+ if (0 == smartlist_len(pending_cb_messages)) {
+ UNLOCK_LOGS();
+ return;
+ }
+
+ messages = pending_cb_messages;
+ pending_cb_messages = smartlist_create();
+ do {
+ SMARTLIST_FOREACH_BEGIN(messages, pending_cb_message_t *, msg) {
+ const int severity = msg->severity;
+ const int domain = msg->domain;
+ for (lf = logfiles; lf; lf = lf->next) {
+ if (! lf->callback || lf->seems_dead ||
+ ! (lf->severities->masks[SEVERITY_MASK_IDX(severity)] & domain)) {
+ continue;
+ }
+ lf->callback(severity, domain, msg->msg);
+ }
+ tor_free(msg->msg);
+ tor_free(msg);
+ } SMARTLIST_FOREACH_END(msg);
+ smartlist_clear(messages);
+
+ messages_tmp = pending_cb_messages;
+ pending_cb_messages = messages;
+ messages = messages_tmp;
+ } while (smartlist_len(messages));
+
+ smartlist_free(messages);
+
+ UNLOCK_LOGS();
+}
+
/** Close any log handlers added by add_temp_log() or marked by
* mark_logs_temp(). */
void
@@ -682,13 +750,11 @@ add_file_log(const log_severity_list_t *severity, const char *filename)
logfiles->needs_close = 1;
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();
}
+ UNLOCK_LOGS();
return 0;
}
@@ -751,7 +817,7 @@ log_level_to_string(int level)
static const char *domain_list[] = {
"GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM",
"HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV",
- "OR", "EDGE", "ACCT", "HIST", NULL
+ "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", NULL
};
/** Return a bitmask for the log domain for which <b>domain</b> is the name,
@@ -929,65 +995,6 @@ switch_logs_debug(void)
UNLOCK_LOGS();
}
-#ifdef HAVE_EVENT_SET_LOG_CALLBACK
-/** A string which, if it appears in a libevent log, should be ignored. */
-static const char *suppress_msg = NULL;
-/** Callback function passed to event_set_log() so we can intercept
- * log messages from libevent. */
-static void
-libevent_logging_callback(int severity, const char *msg)
-{
- char buf[1024];
- size_t n;
- if (suppress_msg && strstr(msg, suppress_msg))
- return;
- n = strlcpy(buf, msg, sizeof(buf));
- if (n && n < sizeof(buf) && buf[n-1] == '\n') {
- buf[n-1] = '\0';
- }
- switch (severity) {
- case _EVENT_LOG_DEBUG:
- log(LOG_DEBUG, LD_NOCB|LD_NET, "Message from libevent: %s", buf);
- break;
- case _EVENT_LOG_MSG:
- log(LOG_INFO, LD_NOCB|LD_NET, "Message from libevent: %s", buf);
- break;
- case _EVENT_LOG_WARN:
- log(LOG_WARN, LD_NOCB|LD_GENERAL, "Warning from libevent: %s", buf);
- break;
- case _EVENT_LOG_ERR:
- log(LOG_ERR, LD_NOCB|LD_GENERAL, "Error from libevent: %s", buf);
- break;
- default:
- log(LOG_WARN, LD_NOCB|LD_GENERAL, "Message [%d] from libevent: %s",
- severity, buf);
- break;
- }
-}
-/** Set hook to intercept log messages from libevent. */
-void
-configure_libevent_logging(void)
-{
- event_set_log_callback(libevent_logging_callback);
-}
-/** Ignore any libevent log message that contains <b>msg</b>. */
-void
-suppress_libevent_log_msg(const char *msg)
-{
- suppress_msg = msg;
-}
-#else
-void
-configure_libevent_logging(void)
-{
-}
-void
-suppress_libevent_log_msg(const char *msg)
-{
- (void)msg;
-}
-#endif
-
#if 0
static void
dump_log_info(logfile_t *lf)