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 <veill...@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 :|

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to