X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=common-src%2Fdebug.c;h=dff138337fb66c36df5b8f3618a8ad6a6136ae60;hb=2627875b7d18858bc1f9f7652811e4d8c15a23eb;hp=7adbc00b241b2346c73914e6fb70d2193f4afca0;hpb=94a044f90357edefa6f4ae9f0b1d5885b0e34aee;p=debian%2Famanda diff --git a/common-src/debug.c b/common-src/debug.c index 7adbc00..dff1383 100644 --- a/common-src/debug.c +++ b/common-src/debug.c @@ -37,6 +37,10 @@ #include "timestamp.h" #include "conffile.h" +#ifdef HAVE_GLIBC_BACKTRACE +#include +#endif + /* Minimum file descriptor on which to keep the debug file. This is intended * to keep the descriptor "out of the way" of other processing. It's not clear * that this is required any longer, but it doesn't hurt anything. @@ -60,7 +64,7 @@ static time_t open_time; static void (*logerror_fn)(char *) = NULL; /* storage for global variables */ -erroutput_type_t erroutput_type = ERR_INTERACTIVE; +erroutput_type_t erroutput_type = ERR_FROM_CONTEXT; int error_exit_status = 1; /* static function prototypes */ @@ -122,29 +126,60 @@ debug_logging_handler(const gchar *log_domain G_GNUC_UNUSED, gpointer user_data G_GNUC_UNUSED) { char *maxlevel = NULL; + pcontext_t context = get_pcontext(); + + /* scriptutil context doesn't do any logging except for critical + * and error levels */ + if (context != CONTEXT_SCRIPTUTIL) { + /* convert the highest level to a string and dbprintf it */ + if (log_level & G_LOG_LEVEL_ERROR) + maxlevel = _("error (fatal): "); + else if (log_level & G_LOG_LEVEL_CRITICAL) + maxlevel = _("critical (fatal): "); + else if (log_level & G_LOG_LEVEL_WARNING) + maxlevel = _("warning: "); + else if (log_level & G_LOG_LEVEL_MESSAGE) + maxlevel = _("message: "); + else if (log_level & G_LOG_LEVEL_INFO) + maxlevel = _("info: "); + else + maxlevel = ""; /* no level displayed for debugging */ - /* convert the highest level to a string and dbprintf it */ - if (log_level & G_LOG_LEVEL_ERROR) - maxlevel = _("error (fatal): "); - else if (log_level & G_LOG_LEVEL_CRITICAL) - maxlevel = _("critical (fatal): "); - else if (log_level & G_LOG_LEVEL_WARNING) - maxlevel = _("warning: "); - else if (log_level & G_LOG_LEVEL_MESSAGE) - maxlevel = _("message: "); - else if (log_level & G_LOG_LEVEL_INFO) - maxlevel = _("info: "); - else - maxlevel = ""; /* no level displayed for debugging */ - - debug_printf("%s%s\n", maxlevel, message); + debug_printf("%s%s\n", maxlevel, message); + } /* error and critical levels have special handling */ if (log_level & (G_LOG_LEVEL_ERROR|G_LOG_LEVEL_CRITICAL)) { - if (erroutput_type & ERR_AMANDALOG && logerror_fn != NULL) + erroutput_type_t local_erroutput; + + /* Calculate a local version of erroutput_type, based on the + * context if the process has not set erroutput_type explicitly */ + if (!(erroutput_type & ERR_FROM_CONTEXT)) { + local_erroutput = erroutput_type; + } else { + switch (context) { + case CONTEXT_SCRIPTUTIL: + local_erroutput = ERR_INTERACTIVE; + break; + + case CONTEXT_DAEMON: + local_erroutput = ERR_INTERACTIVE + | ERR_AMANDALOG + | ERR_SYSLOG; + break; + + case CONTEXT_CMDLINE: + case CONTEXT_DEFAULT: + default: + local_erroutput = ERR_INTERACTIVE; + break; + } + } + + if (local_erroutput & ERR_AMANDALOG && logerror_fn != NULL) (*logerror_fn)((char *)message); /* discard 'const' */ - if (erroutput_type & ERR_SYSLOG) { + if (local_erroutput & ERR_SYSLOG) { #ifdef LOG_AUTH openlog(get_pname(), LOG_PID, LOG_AUTH); #else @@ -154,11 +189,21 @@ debug_logging_handler(const gchar *log_domain G_GNUC_UNUSED, closelog(); } - if (erroutput_type & ERR_INTERACTIVE) { - g_fprintf(stderr, "%s: %s: %s\n", get_pname(), msg_timestamp(), message); + if (local_erroutput & ERR_INTERACTIVE) { + g_fprintf(stderr, "%s: %s\n", get_pname(), message); fflush(stderr); } +#ifdef HAVE_GLIBC_BACKTRACE + /* try logging a traceback to the debug log */ + if (db_fd != -1) { + void *stack[32]; + int naddrs; + naddrs = backtrace(stack, sizeof(stack)/sizeof(*stack)); + backtrace_symbols_fd(stack, naddrs, db_fd); + } +#endif + /* we're done */ if (log_level & G_LOG_LEVEL_CRITICAL) exit(error_exit_status); @@ -230,7 +275,7 @@ debug_setup_1(char *config, char *subdir) dbgdir = vstralloc(AMANDA_DBGDIR, "/", subdir, "/", NULL); else dbgdir = stralloc2(AMANDA_DBGDIR, "/"); - if(mkpdir(dbgdir, 02700, get_client_uid(), get_client_gid()) == -1) { + if(mkpdir(dbgdir, 0700, get_client_uid(), get_client_gid()) == -1) { error(_("create debug directory \"%s\": %s"), dbgdir, strerror(errno)); /*NOTREACHED*/ @@ -365,9 +410,10 @@ debug_setup_2( /* * Make the first debug log file entry. */ - debug_printf(_("pid %ld ruid %ld euid %ld: %s at %s"), + debug_printf(_("pid %ld ruid %ld euid %ld version %s: %s at %s"), (long)getpid(), (long)getuid(), (long)geteuid(), + VERSION, annotation, ctime(&open_time)); } @@ -396,6 +442,19 @@ msg_timestamp(void) * ---- public functions */ +void +debug_init(void) +{ + debug_setup_logging(); + + /* the scriptutil context does not create a debug log, since such + * processes are invoked many times. + */ + if (get_pcontext() != CONTEXT_SCRIPTUTIL) { + debug_open(get_ptype()); + } +} + void set_logerror(void (*f)(char *)) { @@ -633,6 +692,7 @@ printf_arglist_function(void debug_printf, const char *, format) { va_list argp; int save_errno; + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; /* * It is common in the code to call dbprintf to write out @@ -648,11 +708,16 @@ printf_arglist_function(void debug_printf, const char *, format) db_file = stderr; } if(db_file != NULL) { - g_fprintf(db_file, "%s: %s: ", msg_timestamp(), get_pname()); + g_static_mutex_lock(&mutex); + if (db_file != stderr) + g_fprintf(db_file, "%s: %s: ", msg_timestamp(), get_pname()); + else + g_fprintf(db_file, "%s: ", get_pname()); arglist_start(argp, format); g_vfprintf(db_file, format, argp); arglist_end(argp); fflush(db_file); + g_static_mutex_unlock(&mutex); } errno = save_errno; }