int (*write_to_log)(log_id_t log_id, log_priority prio, const char *tag, const char *msg, struct timespec *tp_mono) = NULL;
void (*destroy_backend)();
+int (*stash_failed_log)(log_id_t log_id, log_priority prio, const char *tag, const char *msg) = NULL;
+static int stash_critical(log_id_t log_id, log_priority prio, const char *tag, const char *msg);
+
pthread_rwlock_t log_limiter_lock = PTHREAD_RWLOCK_INITIALIZER;
static pthread_mutex_t log_construction_lock = PTHREAD_MUTEX_INITIALIZER;
static bool is_initialized = false;
limiter_apply_to_all_buffers = log_config_get_int(config,
"limiter_apply_to_all_buffers",
DEFAULT_CONFIG_LIMITER_APPLY_TO_ALL_BUFFERS);
+
+ const char *stash_failed_log_method = log_config_get(config, "stash_failed_log_method");
+ if (stash_failed_log_method) {
+#ifndef UNIT_TEST
+ if (strcmp(stash_failed_log_method, "critical") == 0)
+ stash_failed_log = stash_critical;
+#endif
+ }
}
void __update_plog(const struct log_config *conf)
len = sizeof buf - 1;
struct timespec tp;
+ int r;
if (deduplicate_func && !clock_gettime(CLOCK_MONOTONIC, &tp)) {
if (deduplicate_func(buf, len, &tp))
return DLOG_ERROR_NONE;
- return write_to_log(log_id, prio, tag, buf, &tp);
- }
+ r = write_to_log(log_id, prio, tag, buf, &tp);
+ } else
+ r = write_to_log(log_id, prio, tag, buf, NULL);
- return write_to_log(log_id, prio, tag, buf, NULL);
+ if (r < 0 && stash_failed_log)
+ r = stash_failed_log(log_id, prio, tag, buf);
+
+ return r;
}
static int __write_to_log(log_id_t log_id, int prio, const char *tag, const char *fmt, va_list ap, bool check_should_log, bool secure_log)
* but giving this guarantee makes everything a lot simpler as it removes
* the risk of something suddenly becoming NULL during processing. */
if (!initialize() || !write_to_log)
+ // TODO: We could consider stashing the failed log here
ret = DLOG_ERROR_NOT_PERMITTED;
else if (secure_log && !enable_secure_logs)
ret = 0;
__critical_log_child(main_pid, main_tid, log_id, prio, tag, fmt, ap);
}
+static void stash_critical_inner(log_id_t log_id, log_priority prio, const char *tag, const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ __critical_log(log_id, prio, tag, fmt, ap);
+ va_end(ap);
+}
+
+static int stash_critical(log_id_t log_id, log_priority prio, const char *tag, const char *msg) {
+ stash_critical_inner(log_id, prio, tag, "FAILED TO LOG: %s", msg);
+ return 0;
+}
+
int __dlog_critical_print(log_id_t log_id, int prio, const char *tag, const char *fmt, ...)
{
va_list ap;