|  | @@ -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
 |