/*
*
* Compiz crash handler plugin
*
* crashhandler.c
*
* Copyright : (C) 2006 by Dennis Kasprzyk
* E-mail : onestone@beryl-project.org
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <compiz.h>
#include "crashhandler_options.h"
static CompDisplay *cDisplay;
static void
crash_handler (int sig)
{
if (sig == SIGSEGV || sig == SIGFPE || sig == SIGILL || sig == SIGABRT)
{
static int count = 0;
if (++count > 1)
exit (1);
// backtrace
char cmd[1024];
sprintf (cmd, "echo -e \"set prompt\nthread apply all bt full\n"
"echo \\\\\\n\necho \\\\\\n\nbt\nquit\" > /tmp/gdb.tmp;"
"gdb -q %s %i < /tmp/gdb.tmp | "
"grep -v \"No symbol table\" | "
"tee /tmp/compiz_crash-%i.out; rm -f /tmp/gdb.tmp; "
"echo \"\n[CRASH_HANDLER]: "
"\\\"/tmp/compiz_crash-%i.out\\\" created!\n\"",
programName, getpid (), getpid (), getpid () );
system (cmd);
if (crashhandlerGetStartWm (cDisplay) )
{
if (fork () == 0)
{
setsid ();
putenv (cDisplay->displayString);
execl ("/bin/sh", "/bin/sh", "-c",
crashhandlerGetWmCmd (cDisplay), NULL);
exit (0);
}
}
exit (1);
}
}
static void
crashhandlerDisplayOptionChanged (CompDisplay *d,
CompOption *opt,
CrashhandlerDisplayOptions num)
{
switch (num)
{
case CrashhandlerDisplayOptionEnabled:
if (crashhandlerGetEnabled (d) )
{
// enable crash handler
signal (SIGSEGV, crash_handler);
signal (SIGFPE, crash_handler);
signal (SIGILL, crash_handler);
signal (SIGABRT, crash_handler);
}
else
{
// disable crash handler
signal (SIGSEGV, SIG_DFL);
signal (SIGFPE, SIG_DFL);
signal (SIGILL, SIG_DFL);
signal (SIGABRT, SIG_DFL);
}
break;
default:
break;
}
}
static Bool
crashhandlerInitDisplay (CompPlugin *p,
CompDisplay *d)
{
cDisplay = d;
if (crashhandlerGetEnabled (d) )
{
// segmentation fault
signal (SIGSEGV, crash_handler);
// floating point exception
signal (SIGFPE, crash_handler);
// illegal instruction
signal (SIGILL, crash_handler);
// abort
signal (SIGABRT, crash_handler);
}
crashhandlerSetEnabledNotify (d, crashhandlerDisplayOptionChanged);
return TRUE;
}
static void
crashhandlerFiniDisplay (CompPlugin *p,
CompDisplay *d)
{
signal (SIGSEGV, SIG_DFL);
signal (SIGFPE, SIG_DFL);
signal (SIGILL, SIG_DFL);
signal (SIGABRT, SIG_DFL);
}
static int
crashhandlerGetVersion (CompPlugin *plugin,
int version)
{
return ABIVERSION;
}
CompPluginVTable crashhandlerVTable = {
"crashhandler",
crashhandlerGetVersion,
0,
0,
0,
crashhandlerInitDisplay,
crashhandlerFiniDisplay,
0,
0,
0,
0,
0,
0,
0,
0
};
CompPluginVTable *
getCompPluginInfo (void)
{
return &crashhandlerVTable;
}
syntax highlighted by Code2HTML, v. 0.9.1