2005-02-03 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* log.c: (syslog_sigsafe) Reduce scope of syslog_fd: it is accessed
inside this function only.
(open_crashlog) New function to open /var/tmp/quagga.<daemon>.crashlog
with flags O_WRONLY|O_CREAT|O_EXCL to save some crash info.
(zlog_signal,_zlog_assert_failed) Increase logging priority from
LOG_ERR to LOG_CRIT. If no file logging is configured, try to use
open_crashlog to create a crash logfile.
(zlog_backtrace_sigsafe) If a crashlog file descriptor is open,
dump a backtrace to that file.
diff --git a/lib/ChangeLog b/lib/ChangeLog
index a69abc5..6f9c39a 100644
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,3 +1,15 @@
+2005-02-03 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
+
+ * log.c: (syslog_sigsafe) Reduce scope of syslog_fd: it is accessed
+ inside this function only.
+ (open_crashlog) New function to open /var/tmp/quagga.<daemon>.crashlog
+ with flags O_WRONLY|O_CREAT|O_EXCL to save some crash info.
+ (zlog_signal,_zlog_assert_failed) Increase logging priority from
+ LOG_ERR to LOG_CRIT. If no file logging is configured, try to use
+ open_crashlog to create a crash logfile.
+ (zlog_backtrace_sigsafe) If a crashlog file descriptor is open,
+ dump a backtrace to that file.
+
2005-02-02 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* if.h: Declare if_flag_dump.
diff --git a/lib/log.c b/lib/log.c
index 2efc30f..dbd378f 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -1,5 +1,5 @@
/*
- * $Id: log.c,v 1.23 2005/01/18 22:18:59 ajs Exp $
+ * $Id: log.c,v 1.24 2005/02/03 16:42:40 ajs Exp $
*
* Logging of zebra
* Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro
@@ -31,6 +31,9 @@
#include <sys/un.h>
#endif
+static int crashlog_fd = -1; /* Used for last-resort crash logfile when a
+ signal is caught. */
+
struct zlog *zlog_default = NULL;
const char *zlog_proto_names[] =
@@ -197,8 +200,6 @@
}
#endif
-static int syslog_fd = -1;
-
/* Needs to be enhanced to support Solaris. */
static int
syslog_connect(void)
@@ -233,6 +234,7 @@
static void
syslog_sigsafe(int priority, const char *msg, size_t msglen)
{
+ static int syslog_fd = -1;
char buf[sizeof("<1234567890>ripngd[1234567890]: ")+msglen+50];
char *s;
@@ -258,6 +260,38 @@
#undef LOC
}
+static int
+open_crashlog(void)
+{
+#define CRASHLOG_PREFIX "/var/tmp/quagga."
+#define CRASHLOG_SUFFIX "crashlog"
+ if (zlog_default && zlog_default->ident)
+ {
+ /* Avoid strlen since it is not async-signal-safe. */
+ const char *p;
+ size_t ilen;
+
+ for (p = zlog_default->ident, ilen = 0; *p; p++)
+ ilen++;
+ {
+ char buf[sizeof(CRASHLOG_PREFIX)+ilen+sizeof(CRASHLOG_SUFFIX)+3];
+ char *s = buf;
+#define LOC s,buf+sizeof(buf)-s
+ s = str_append(LOC, CRASHLOG_PREFIX);
+ s = str_append(LOC, zlog_default->ident);
+ s = str_append(LOC, ".");
+ s = str_append(LOC, CRASHLOG_SUFFIX);
+#undef LOC
+ *s = '\0';
+ return open(buf, O_WRONLY|O_CREAT|O_EXCL, LOGFILE_MASK);
+ }
+ }
+ return open(CRASHLOG_PREFIX CRASHLOG_SUFFIX, O_WRONLY|O_CREAT|O_EXCL,
+ LOGFILE_MASK);
+#undef CRASHLOG_SUFFIX
+#undef CRASHLOG_PREFIX
+}
+
/* Note: the goal here is to use only async-signal-safe functions. */
void
zlog_signal(int signo, const char *action
@@ -301,17 +335,21 @@
*s++ = '\n';
/* N.B. implicit priority is most severe */
-#define PRI LOG_ERR
+#define PRI LOG_CRIT
-#define DUMP(FP) write(fileno(FP),buf,s-buf);
+#define DUMP(FD) write(FD, buf, s-buf);
+ /* If no file logging configured, try to write to fallback log file. */
+ if ((!zlog_default || !zlog_default->fp) &&
+ ((crashlog_fd = open_crashlog()) >= 0))
+ DUMP(crashlog_fd)
if (!zlog_default)
- DUMP(stderr)
+ DUMP(fileno(stderr))
else
{
if ((PRI <= zlog_default->maxlvl[ZLOG_DEST_FILE]) && zlog_default->fp)
- DUMP(zlog_default->fp)
+ DUMP(fileno(zlog_default->fp))
if (PRI <= zlog_default->maxlvl[ZLOG_DEST_STDOUT])
- DUMP(stdout)
+ DUMP(fileno(stdout))
/* Remove trailing '\n' for monitor and syslog */
*--s = '\0';
if (PRI <= zlog_default->maxlvl[ZLOG_DEST_MONITOR])
@@ -353,25 +391,27 @@
s = num_append(LOC,size);
s = str_append(LOC," stack frames:\n");
-#define DUMP(FP) { \
+#define DUMP(FD) { \
if (program_counter) \
{ \
- write(fileno(FP),pclabel,sizeof(pclabel)-1); \
- backtrace_symbols_fd(&program_counter, 1, fileno(FP)); \
+ write(FD, pclabel, sizeof(pclabel)-1); \
+ backtrace_symbols_fd(&program_counter, 1, FD); \
} \
- write(fileno(FP),buf,s-buf); \
- backtrace_symbols_fd(array, size, fileno(FP)); \
+ write(FD, buf, s-buf); \
+ backtrace_symbols_fd(array, size, FD); \
}
+ if (crashlog_fd >= 0)
+ DUMP(crashlog_fd)
if (!zlog_default)
- DUMP(stderr)
+ DUMP(fileno(stderr))
else
{
if ((priority <= zlog_default->maxlvl[ZLOG_DEST_FILE]) &&
zlog_default->fp)
- DUMP(zlog_default->fp)
+ DUMP(fileno(zlog_default->fp))
if (priority <= zlog_default->maxlvl[ZLOG_DEST_STDOUT])
- DUMP(stdout)
+ DUMP(fileno(stdout))
/* Remove trailing '\n' for monitor and syslog */
*--s = '\0';
if (priority <= zlog_default->maxlvl[ZLOG_DEST_MONITOR])
@@ -493,9 +533,21 @@
_zlog_assert_failed (const char *assertion, const char *file,
unsigned int line, const char *function)
{
- zlog_err("Assertion `%s' failed in file %s, line %u, function %s",
- assertion,file,line,(function ? function : "?"));
- zlog_backtrace(LOG_ERR);
+ if (zlog_default && !zlog_default->fp)
+ {
+ /* Force fallback file logging. */
+ int fd;
+ FILE *fp;
+
+ if (((fd = open_crashlog()) >= 0) && ((fp = fdopen(fd, "w")) != NULL))
+ {
+ zlog_default->fp = fp;
+ zlog_default->maxlvl[ZLOG_DEST_FILE] = LOG_ERR;
+ }
+ }
+ zlog(NULL, LOG_CRIT, "Assertion `%s' failed in file %s, line %u, function %s",
+ assertion,file,line,(function ? function : "?"));
+ zlog_backtrace(LOG_CRIT);
abort();
}