From dae1184302834b52cff438fbf5322cd1c9c79c06 Mon Sep 17 00:00:00 2001 From: Bernd Schubert Date: Wed, 10 Jul 2024 23:04:46 +0200 Subject: Add syslog and fatal signal handler feature I see random ENOTCONN failures in xfstest generic/013 and generic/014 in my branch, but earliest on the 2nd run - takes ~12hours to get the issue, but then there are no further information logged. ENOTCONN points to a daemon crash - I need backtraces and a core dump. This adds optional handling of fatal signals to print a core dump and optional syslog logging with these new public functions: fuse_set_fail_signal_handlers() In addition to the existing fuse_set_signal_handlers(). This is not enabled together with fuse_set_signal_handlers(), as it is change in behavior and file systems might already have their own fatal handlers. fuse_log_enable_syslog Print logs to syslog instead of stderr fuse_log_close_syslog Close syslog (for now just does closelog()) Code in fuse_signals.c is also updated, to be an array of signals, and setting signal handlers is now down with a for-loop instead of one hand coded set_one_signal_handler() per signal. --- lib/fuse_log.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 4 deletions(-) (limited to 'lib/fuse_log.c') diff --git a/lib/fuse_log.c b/lib/fuse_log.c index 0d268ab..95d6379 100644 --- a/lib/fuse_log.c +++ b/lib/fuse_log.c @@ -12,12 +12,56 @@ #include #include +#include +#include -static void default_log_func( - __attribute__(( unused )) enum fuse_log_level level, - const char *fmt, va_list ap) +#define MAX_SYSLOG_LINE_LEN 512 + +static bool to_syslog = false; + +static void default_log_func(__attribute__((unused)) enum fuse_log_level level, + const char *fmt, va_list ap) { - vfprintf(stderr, fmt, ap); + if (to_syslog) { + int sys_log_level; + + /* + * with glibc fuse_log_level has identical values as + * syslog levels, but we also support BSD - better we convert to + * be sure. + */ + switch (level) { + case FUSE_LOG_DEBUG: + sys_log_level = LOG_DEBUG; + break; + case FUSE_LOG_INFO: + sys_log_level = LOG_INFO; + break; + case FUSE_LOG_NOTICE: + sys_log_level = LOG_NOTICE; + break; + case FUSE_LOG_WARNING: + sys_log_level = LOG_WARNING; + break; + case FUSE_LOG_ERR: + sys_log_level = LOG_ERR; + break; + case FUSE_LOG_CRIT: + sys_log_level = LOG_CRIT; + break; + case FUSE_LOG_ALERT: + sys_log_level = LOG_ALERT; + break; + case FUSE_LOG_EMERG: + sys_log_level = LOG_EMERG; + } + + char log[MAX_SYSLOG_LINE_LEN]; + vsnprintf(log, MAX_SYSLOG_LINE_LEN, fmt, ap); + syslog(sys_log_level, "%s", log); + } else { + vfprintf(stderr, fmt, ap); + } } static fuse_log_func_t log_func = default_log_func; @@ -38,3 +82,15 @@ void fuse_log(enum fuse_log_level level, const char *fmt, ...) log_func(level, fmt, ap); va_end(ap); } + +void fuse_log_enable_syslog(const char *ident, int option, int facility) +{ + to_syslog = true; + + openlog(ident, option, facility); +} + +void fuse_log_close_syslog(void) +{ + closelog(); +} \ No newline at end of file -- cgit v1.2.3