Browse Source

Add a mechanism for the logging system to report queued callbacks

Sometimes the logging system will queue a log message for later.
When it does this, the callback will either get flushed at the next
safe time, or from the second-elapsed callback.

But we're trying to eliminate the second-elapsed callback, so let's
make a way for the log system to tell its users about this.
Nick Mathewson 6 years ago
parent
commit
b0224bf728
2 changed files with 27 additions and 0 deletions
  1. 25 0
      src/common/log.c
  2. 2 0
      src/common/torlog.h

+ 25 - 0
src/common/log.c

@@ -170,6 +170,9 @@ typedef struct pending_log_message_t {
 /** Log messages waiting to be replayed onto callback-based logs */
 static smartlist_t *pending_cb_messages = NULL;
 
+/** Callback to invoke when pending_cb_messages becomes nonempty. */
+static pending_callback_callback pending_cb_cb = NULL;
+
 /** Log messages waiting to be replayed once the logging system is initialized.
  */
 static smartlist_t *pending_startup_messages = NULL;
@@ -538,6 +541,9 @@ logfile_deliver(logfile_t *lf, const char *buf, size_t msg_len,
         smartlist_add(pending_cb_messages,
             pending_log_message_new(severity,domain,NULL,msg_after_prefix));
         *callbacks_deferred = 1;
+        if (smartlist_len(pending_cb_messages) == 1 && pending_cb_cb) {
+          pending_cb_cb();
+        }
       }
     } else {
       lf->callback(severity, domain, msg_after_prefix);
@@ -825,6 +831,7 @@ logs_free_all(void)
   logfiles = NULL;
   messages = pending_cb_messages;
   pending_cb_messages = NULL;
+  pending_cb_cb = NULL;
   messages2 = pending_startup_messages;
   pending_startup_messages = NULL;
   UNLOCK_LOGS();
@@ -987,6 +994,24 @@ add_temp_log(int min_severity)
   UNLOCK_LOGS();
 }
 
+/**
+ * Register "cb" as the callback to call when there are new pending log
+ * callbacks to be flushed with flush_pending_log_callbacks().
+ *
+ * Note that this callback, if present, can be invoked from any thread.
+ *
+ * This callback must not log.
+ *
+ * It is intentional that this function contains the name "callback" twice: it
+ * sets a "callback" to be called on the condition that there is a "pending
+ * callback".
+ **/
+void
+logs_set_pending_callback_callback(pending_callback_callback cb)
+{
+  pending_cb_cb = cb;
+}
+
 /**
  * Add a log handler to send messages in <b>severity</b>
  * to the function <b>cb</b>.

+ 2 - 0
src/common/torlog.h

@@ -154,6 +154,8 @@ int add_android_log(const log_severity_list_t *severity,
                     const char *android_identity_tag);
 #endif // HAVE_ANDROID_LOG_H.
 int add_callback_log(const log_severity_list_t *severity, log_callback cb);
+typedef void (*pending_callback_callback)(void);
+void logs_set_pending_callback_callback(pending_callback_callback cb);
 void logs_set_domain_logging(int enabled);
 int get_min_log_level(void);
 void switch_logs_debug(void);