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.
This commit is contained in:
Nick Mathewson 2018-05-01 10:05:22 -04:00
parent 4cf6b67f5e
commit b0224bf728
2 changed files with 27 additions and 0 deletions

View File

@ -170,6 +170,9 @@ typedef struct pending_log_message_t {
/** Log messages waiting to be replayed onto callback-based logs */ /** Log messages waiting to be replayed onto callback-based logs */
static smartlist_t *pending_cb_messages = NULL; 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. /** Log messages waiting to be replayed once the logging system is initialized.
*/ */
static smartlist_t *pending_startup_messages = NULL; 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, smartlist_add(pending_cb_messages,
pending_log_message_new(severity,domain,NULL,msg_after_prefix)); pending_log_message_new(severity,domain,NULL,msg_after_prefix));
*callbacks_deferred = 1; *callbacks_deferred = 1;
if (smartlist_len(pending_cb_messages) == 1 && pending_cb_cb) {
pending_cb_cb();
}
} }
} else { } else {
lf->callback(severity, domain, msg_after_prefix); lf->callback(severity, domain, msg_after_prefix);
@ -825,6 +831,7 @@ logs_free_all(void)
logfiles = NULL; logfiles = NULL;
messages = pending_cb_messages; messages = pending_cb_messages;
pending_cb_messages = NULL; pending_cb_messages = NULL;
pending_cb_cb = NULL;
messages2 = pending_startup_messages; messages2 = pending_startup_messages;
pending_startup_messages = NULL; pending_startup_messages = NULL;
UNLOCK_LOGS(); UNLOCK_LOGS();
@ -987,6 +994,24 @@ add_temp_log(int min_severity)
UNLOCK_LOGS(); 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> * Add a log handler to send messages in <b>severity</b>
* to the function <b>cb</b>. * to the function <b>cb</b>.

View File

@ -154,6 +154,8 @@ int add_android_log(const log_severity_list_t *severity,
const char *android_identity_tag); const char *android_identity_tag);
#endif // HAVE_ANDROID_LOG_H. #endif // HAVE_ANDROID_LOG_H.
int add_callback_log(const log_severity_list_t *severity, log_callback cb); 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); void logs_set_domain_logging(int enabled);
int get_min_log_level(void); int get_min_log_level(void);
void switch_logs_debug(void); void switch_logs_debug(void);