|
@@ -103,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
|
|
@@ -261,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);
|
|
@@ -268,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)) {
|
|
@@ -312,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;
|
|
|
}
|
|
@@ -551,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
|
|
@@ -609,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
|