summaryrefslogtreecommitdiff
path: root/beryl-plugins/src/crashhandler.c
diff options
context:
space:
mode:
authorquinn <quinn@d7aaf104-2d23-0410-ae22-9d23157bf5a3>2006-09-27 23:19:52 +0000
committerquinn <quinn@d7aaf104-2d23-0410-ae22-9d23157bf5a3>2006-09-27 23:19:52 +0000
commit4c9796dddab60529fff57638d3cb0d8ca830a3fe (patch)
tree1c54f385f71dc9897381c7b266ff1090137a74e1 /beryl-plugins/src/crashhandler.c
parent6e36e85e06f7cf5edc75016bc2bb2612c0ee80c1 (diff)
downloadmarex-dev-4c9796dddab60529fff57638d3cb0d8ca830a3fe.tar.gz
marex-dev-4c9796dddab60529fff57638d3cb0d8ca830a3fe.tar.bz2
move in beryl-plugins
git-svn-id: file:///beryl/trunk@325 d7aaf104-2d23-0410-ae22-9d23157bf5a3
Diffstat (limited to 'beryl-plugins/src/crashhandler.c')
-rw-r--r--beryl-plugins/src/crashhandler.c288
1 files changed, 288 insertions, 0 deletions
diff --git a/beryl-plugins/src/crashhandler.c b/beryl-plugins/src/crashhandler.c
new file mode 100644
index 0000000..fb3530a
--- /dev/null
+++ b/beryl-plugins/src/crashhandler.c
@@ -0,0 +1,288 @@
+/**
+ *
+ * Beryl crash handler plugin
+ *
+ * crashhandler.c
+ *
+ * Copyright : (C) 2006 by Dennis Kasprzyk
+ * E-mail : dennis.kasprzyk@rwth-aachen.de
+ *
+ *
+ * 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 <beryl.h>
+
+#define GET_CRASHHANDLER_DISPLAY(d) \
+ ((CrashhandlerDisplay *) (d)->privates[displayPrivateIndex].ptr)
+
+#define CRASHHANDLER_DISPLAY(d) \
+ CrashhandlerDisplay *cd = GET_CRASHHANDLER_DISPLAY (d)
+
+#define CRASHHANDLER_DISPLAY_OPTION_ENABLED 0
+#define CRASHHANDLER_DISPLAY_OPTION_START_WM 1
+#define CRASHHANDLER_DISPLAY_OPTION_WM 2
+#define CRASHHANDLER_DISPLAY_OPTION_NUM 3
+
+#define CRASHHANDLER_DISPLAY_OPTION_ENABLED_DEFAULT TRUE
+#define CRASHHANDLER_DISPLAY_OPTION_START_WM_DEFAULT FALSE
+#define CRASHHANDLER_DISPLAY_OPTION_WM_DEFAULT ""
+
+#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
+
+static int displayPrivateIndex = 0;
+static CompDisplay *cDisplay;
+
+typedef struct _CrashhandlerDisplay
+{
+ int screenPrivateIndex;
+ CompOption opt[CRASHHANDLER_DISPLAY_OPTION_NUM];
+} CrashhandlerDisplay;
+
+void
+crash_handler (int sig)
+{
+ if (sig == SIGSEGV || sig == SIGFPE || sig == SIGILL || sig == SIGABRT)
+ {
+ CRASHHANDLER_DISPLAY (cDisplay);
+ static int count = 0;
+ if (++count > 1)
+ exit (1);
+ // backtrace
+ char cmd[1024];
+ sprintf (cmd,
+ "echo -e \"set prompt\nthread apply all bt full\necho \\\\\\n\necho \\\\\\n\nbt\nquit\" > /tmp/gdb.tmp; gdb -q %s %i < /tmp/gdb.tmp | grep -v \"No symbol table\" | tee /tmp/beryl_crash-%i.out; rm -f /tmp/gdb.tmp; echo \"\n[CRASH_HANDLER]: \\\"/tmp/beryl_crash-%i.out\\\" created!\n\"",
+ programName, getpid (), getpid (), getpid ());
+ system (cmd);
+
+ if (cd->opt[CRASHHANDLER_DISPLAY_OPTION_START_WM].value.b)
+ {
+ if (fork () == 0)
+ {
+ setsid ();
+ putenv (cDisplay->displayString);
+ execl ("/bin/sh", "/bin/sh", "-c",
+ cd->opt[CRASHHANDLER_DISPLAY_OPTION_WM].value.s, NULL);
+ exit (0);
+ }
+ }
+
+ exit (1);
+ }
+}
+
+static Bool
+crashhandlerSetDisplayOption (CompDisplay * display, char *name,
+ CompOptionValue * value)
+{
+ CompOption *o;
+ int index;
+
+ CRASHHANDLER_DISPLAY (display);
+
+ o = compFindOption (cd->opt, NUM_OPTIONS (cd), name, &index);
+ if (!o)
+ return FALSE;
+
+ switch (index)
+ {
+ case CRASHHANDLER_DISPLAY_OPTION_ENABLED:
+ if (compSetBoolOption (o, value))
+ {
+ if (value->b)
+ {
+ // 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);
+ }
+ return TRUE;
+ }
+ break;
+ case CRASHHANDLER_DISPLAY_OPTION_START_WM:
+ if (compSetBoolOption (o, value))
+ return TRUE;
+ break;
+ case CRASHHANDLER_DISPLAY_OPTION_WM:
+ if (compSetStringOption (o, value))
+ return TRUE;
+ break;
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+static void
+crashhandlerDisplayInitOptions (CrashhandlerDisplay * cd, Display * display)
+{
+ CompOption *o;
+
+ o = &cd->opt[CRASHHANDLER_DISPLAY_OPTION_ENABLED];
+ o->name = "enabled";
+ o->shortDesc = "Enabled";
+ o->longDesc = "Activate crash handler";
+ o->type = CompOptionTypeBool;
+ o->value.b = CRASHHANDLER_DISPLAY_OPTION_ENABLED_DEFAULT;
+
+ o = &cd->opt[CRASHHANDLER_DISPLAY_OPTION_START_WM];
+ o->name = "start_window_manager";
+ o->shortDesc = "Start Window Manager";
+ o->longDesc = "Start other window manager on crash";
+ o->type = CompOptionTypeBool;
+ o->value.b = CRASHHANDLER_DISPLAY_OPTION_START_WM_DEFAULT;
+
+ o = &cd->opt[CRASHHANDLER_DISPLAY_OPTION_WM];
+ o->name = "window_manager_command_line";
+ o->shortDesc = "Window manager command line";
+ o->longDesc = "Window manager command line. DO NOT ENTER COMPIZ HERE!!!";
+ o->type = CompOptionTypeString;
+ o->value.s = strdup (CRASHHANDLER_DISPLAY_OPTION_WM_DEFAULT);
+ o->rest.s.string = 0;
+ o->rest.s.nString = 0;
+
+}
+
+
+static CompOption *
+crashhandlerGetDisplayOptions (CompDisplay * display, int *count)
+{
+ if (display)
+ {
+ CRASHHANDLER_DISPLAY (display);
+
+ *count = NUM_OPTIONS (cd);
+ return cd->opt;
+ }
+ else
+ {
+ CrashhandlerDisplay * cd = malloc(sizeof(CrashhandlerDisplay));
+ Display * d = XOpenDisplay(getenv("DISPLAY"));
+ if (!d)exit(1);
+ crashhandlerDisplayInitOptions(cd,d);
+ *count = NUM_OPTIONS(cd);
+ return cd->opt;
+ }
+}
+
+
+static Bool
+crashhandlerInitDisplay (CompPlugin * p, CompDisplay * d)
+{
+ //Generate a bench display
+ CrashhandlerDisplay *cd =
+ (CrashhandlerDisplay *) malloc (sizeof (CrashhandlerDisplay));
+ //Allocate a private index
+ cd->screenPrivateIndex = allocateScreenPrivateIndex (d);
+ //Check if its valid
+ if (cd->screenPrivateIndex < 0)
+ {
+ //Its invalid so free memory and return
+ free (cd);
+ return FALSE;
+ }
+ crashhandlerDisplayInitOptions (cd, d->display);
+ cDisplay = d;
+
+ if (cd->opt[CRASHHANDLER_DISPLAY_OPTION_ENABLED].value.b)
+ {
+ // segmentation fault
+ signal (SIGSEGV, crash_handler);
+ // floating point exception
+ signal (SIGFPE, crash_handler);
+ // illegal instruction
+ signal (SIGILL, crash_handler);
+ // abort
+ signal (SIGABRT, crash_handler);
+ }
+
+
+
+ //Record the display
+ d->privates[displayPrivateIndex].ptr = cd;
+ return TRUE;
+}
+
+static void
+crashhandlerFiniDisplay (CompPlugin * p, CompDisplay * d)
+{
+ signal (SIGSEGV, SIG_DFL);
+ CRASHHANDLER_DISPLAY (d);
+ //Free the private index
+ freeScreenPrivateIndex (d, cd->screenPrivateIndex);
+ //Free the pointer
+ free (cd);
+}
+
+
+
+static Bool
+crashhandlerInit (CompPlugin * p)
+{
+ displayPrivateIndex = allocateDisplayPrivateIndex ();
+
+ if (displayPrivateIndex < 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+crashhandlerFini (CompPlugin * p)
+{
+ if (displayPrivateIndex >= 0)
+ freeDisplayPrivateIndex (displayPrivateIndex);
+}
+
+
+CompPluginVTable crashhandlerVTable = {
+ "crashhandler",
+ "Crash handler",
+ "Beryl crash handler plugin",
+ crashhandlerInit,
+ crashhandlerFini,
+ crashhandlerInitDisplay,
+ crashhandlerFiniDisplay,
+ 0,
+ 0,
+ 0,
+ 0,
+ crashhandlerGetDisplayOptions,
+ crashhandlerSetDisplayOption,
+ 0,
+ 0,
+ 0,
+ 0,
+ BERYL_ABI_INFO
+};
+
+CompPluginVTable *
+getCompPluginInfo (void)
+{
+ return &crashhandlerVTable;
+}