[libvirt] [PATCH 6/6] Dump the debug buffer to libvirtd.log on fatal signal

In case of imminent crash or upon request (signal USR2), dump the logging buffer to the libvirtd.log file for post-mortem analysis * daemon/libvirtd.c: create a sig_fatal() handler connected to SIGFPE SIGSEGV SIGILL SIGABRT SIGBUS and SIGUSR2, just dumping the log buffer to the libvirtd.log open file descriptor Signed-off-by: Daniel Veillard <veillard@redhat.com> --- daemon/libvirtd.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 51 insertions(+), 0 deletions(-)

On Thu, Mar 03, 2011 at 06:22:17PM +0800, Daniel Veillard wrote:
In case of imminent crash or upon request (signal USR2), dump the logging buffer to the libvirtd.log file for post-mortem analysis * daemon/libvirtd.c: create a sig_fatal() handler connected to SIGFPE SIGSEGV SIGILL SIGABRT SIGBUS and SIGUSR2, just dumping the log buffer to the libvirtd.log open file descriptor
Signed-off-by: Daniel Veillard <veillard@redhat.com> --- daemon/libvirtd.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 51 insertions(+), 0 deletions(-)
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 42e8585..3338336 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -248,6 +248,45 @@ static void sig_handler(int sig, siginfo_t * siginfo, errno = origerrno; }
+static int sig_fatal_dump(void *data ATTRIBUTE_UNUSED, + const char *buf, int len) { + int r; + + r = safewrite(logFD, buf, len); + return(r); +} + +static void sig_fatal(int sig, siginfo_t * siginfo ATTRIBUTE_UNUSED, + void* context ATTRIBUTE_UNUSED) { + struct sigaction sig_action; + int origerrno; + int r; + char buf[100]; + + origerrno = errno; + snprintf(buf, sizeof(buf) - 1, + "Caught signal %d, dumping internal log buffer:\n", sig); + buf[sizeof(buf) - 1] = 0; + r = safewrite(logFD, buf, strlen(buf)); + snprintf(buf, sizeof(buf) - 1, "\n\n ====== start of log =====\n\n"); + r = safewrite(logFD, buf, strlen(buf)); + virLogDump(NULL, sig_fatal_dump); + snprintf(buf, sizeof(buf) - 1, "\n\n ====== end of log =====\n\n"); + r = safewrite(logFD, buf, strlen(buf)); + fsync(logFD); + + /* + * If the signal is fatal, avoid looping over this handler + * by desactivating it + */ + if (sig != SIGUSR2) { + sig_action.sa_flags = SA_SIGINFO; + sig_action.sa_handler = SIG_IGN; + sigaction(sig, &sig_action, NULL); + } + errno = origerrno; +}
I think this code should really be part of the logging.c file. eg create an API like: void virLogEmergencyDumpAll(int signum) And have that dump the cached log buffer to all registered log outputs. We'd have to excluding any syslog one which isn't async signal safe, but the 'stderr' or 'file' log outputs can be made async signal safe. Then, the libvirtd signal handler would just be static void sig_fatal(int sig, siginfo_t * siginfo ATTRIBUTE_UNUSED, void* context ATTRIBUTE_UNUSED) { virLogEmergencyDumpAll(sig); } Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On Thu, Mar 03, 2011 at 11:41:51AM +0000, Daniel P. Berrange wrote:
On Thu, Mar 03, 2011 at 06:22:17PM +0800, Daniel Veillard wrote:
In case of imminent crash or upon request (signal USR2), dump the logging buffer to the libvirtd.log file for post-mortem analysis * daemon/libvirtd.c: create a sig_fatal() handler connected to SIGFPE SIGSEGV SIGILL SIGABRT SIGBUS and SIGUSR2, just dumping the log buffer to the libvirtd.log open file descriptor
[...]
+ /* + * If the signal is fatal, avoid looping over this handler + * by desactivating it + */ + if (sig != SIGUSR2) { + sig_action.sa_flags = SA_SIGINFO; + sig_action.sa_handler = SIG_IGN; + sigaction(sig, &sig_action, NULL); + } + errno = origerrno; +}
I think this code should really be part of the logging.c file. eg create an API like:
void virLogEmergencyDumpAll(int signum)
And have that dump the cached log buffer to all registered log outputs. We'd have to excluding any syslog one which isn't async signal safe, but the 'stderr' or 'file' log outputs can be made async signal safe.
yeah, I just need to double check that we just use file descriptor and not FILE *, but it's trivial to check or convert.
Then, the libvirtd signal handler would just be
static void sig_fatal(int sig, siginfo_t * siginfo ATTRIBUTE_UNUSED, void* context ATTRIBUTE_UNUSED) { virLogEmergencyDumpAll(sig);
well we will still need the above bit of sigaction, but yes, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/
participants (2)
-
Daniel P. Berrange
-
Daniel Veillard