summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Haitzler <raster@rasterman.com>2005-06-15 05:06:45 +0000
committerCarsten Haitzler <raster@rasterman.com>2005-06-15 05:06:45 +0000
commit2ed41fb21f128fc6c6a16df4dbf5b589a4a6c837 (patch)
tree2a424f50d0e19a6f929243999ce677c8d62b2891
parent33323d7f3ae2ae9943c3cf854fce6a81536c557e (diff)
downloadenlightenment-2ed41fb21f128fc6c6a16df4dbf5b589a4a6c837.tar.gz
segv/bus/ill/fpe handler to trap all the nasties and allow debug or recovery
SVN revision: 15329
-rw-r--r--TODO1
-rw-r--r--src/bin/Makefile.am7
-rw-r--r--src/bin/e_alert.c234
-rw-r--r--src/bin/e_alert.h16
-rw-r--r--src/bin/e_includes.h1
-rw-r--r--src/bin/e_main.c43
-rw-r--r--src/bin/e_signals.c96
-rw-r--r--src/bin/e_signals.h11
8 files changed, 391 insertions, 18 deletions
diff --git a/TODO b/TODO
index 246f545acd..174ed8fd58 100644
--- a/TODO
+++ b/TODO
@@ -158,5 +158,4 @@ These are in no particular order:
* remove module config menus (make them part of the module control panel and
as separate executables)
* tip/hint/suggestion dialog app (textblock etc.)
-* segv/restart handler like e16.
diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am
index 4e95bad284..122178def9 100644
--- a/src/bin/Makefile.am
+++ b/src/bin/Makefile.am
@@ -4,6 +4,7 @@ INCLUDES = -I$(includedir) \
-I$(top_srcdir)/src/bin \
-I$(top_srcdir)/src/lib \
@e_cflags@ \
+ @x_cflags@ \
@EDJE_DEF@
bin_PROGRAMS = enlightenment enlightenment_remote enlightenment_eapp
@@ -58,7 +59,8 @@ e_ipc_codec.h \
e_prefix.h \
e_datastore.h \
e_msg.h \
-e_winlist.h
+e_winlist.h \
+e_alert.h
enlightenment_SOURCES = \
e_main.c \
@@ -108,9 +110,10 @@ e_prefix.c \
e_datastore.c \
e_msg.c \
e_winlist.c \
+e_alert.c \
$(ENLIGHTENMENTHEADERS)
-enlightenment_LDFLAGS = -export-dynamic @e_libs@ @dlopen_libs@
+enlightenment_LDFLAGS = -export-dynamic @e_libs@ @x_libs@ @dlopen_libs@
enlightenment_remote_SOURCES = \
e.h \
diff --git a/src/bin/e_alert.c b/src/bin/e_alert.c
new file mode 100644
index 0000000000..a0ffc0b338
--- /dev/null
+++ b/src/bin/e_alert.c
@@ -0,0 +1,234 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+#include "e_alert.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <X11/Xlib.h>
+#include <X11/X.h>
+
+/* FIXME: make this work */
+
+/* local subsystem functions */
+
+/* local subsystem globals */
+static Display *dd = NULL;
+static char *title = NULL, *str1 = NULL, *str2 = NULL, *str3 = NULL;
+static Font font = 0;
+static XFontStruct *fs = NULL;
+
+
+/* externally accessible functions */
+int
+e_alert_init(char *disp)
+{
+ dd = XOpenDisplay(disp);
+ if (!dd) return 0;
+ font = XLoadFont(dd, "fixed");
+ fs = XQueryFont(dd, font);
+
+ /* dont i18n this - i dont want gettext doing anything as this is caleld from a segv */
+ title = "Enlightenment Error";
+ str1 = "(F1) Ignore";
+ str2 = "(F2) Restart";
+ str3 = "(F3) Exit";
+ return 1;
+}
+
+int
+e_alert_shutdown(void)
+{
+ XFreeFont(dd, fs);
+ XCloseDisplay(dd);
+ title = NULL;
+ str1 = NULL;
+ str2 = NULL;
+ str3 = NULL;
+ dd = NULL;
+ font = 0;
+ fs = NULL;
+ return 1;
+}
+
+void
+e_alert_show(char *text)
+{
+ int wid, hih, w, h, i, j, k, mask;
+ XGCValues gcv;
+ GC gc;
+ char line[1024];
+ XEvent ev;
+ XSetWindowAttributes att;
+ int fw, fh, x, y, ww, hh, mh;
+ KeyCode key;
+ int button;
+ Window win = 0, b1 = 0, b2 = 0, b3 = 0;
+ XCharStruct cs;
+
+ if (!text) return;
+
+ if ((!dd) || (!fs))
+ {
+ fprintf(stderr, text);
+ fflush(stderr);
+ exit(-1);
+ }
+
+ ww = 600;
+ hh = 440;
+
+ wid = DisplayWidth(dd, DefaultScreen(dd));
+ hih = DisplayHeight(dd, DefaultScreen(dd));
+ att.background_pixel = WhitePixel(dd, DefaultScreen(dd));
+ att.border_pixel = BlackPixel(dd, DefaultScreen(dd));
+ att.override_redirect = True;
+ mask = CWBackPixel | CWBorderPixel | CWOverrideRedirect;
+
+ win = XCreateWindow(dd, DefaultRootWindow(dd),
+ (wid - ww) / 2, (hih - hh) / 2, ww, hh, 0,
+ CopyFromParent, InputOutput,
+ CopyFromParent, mask, &att);
+
+ b1 = XCreateWindow(dd, win, -100, -100, 1, 1, 0, CopyFromParent,
+ InputOutput, CopyFromParent, mask, &att);
+ b2 = XCreateWindow(dd, win, -100, -100, 1, 1, 0, CopyFromParent,
+ InputOutput, CopyFromParent, mask, &att);
+ b3 = XCreateWindow(dd, win, -100, -100, 1, 1, 0, CopyFromParent,
+ InputOutput, CopyFromParent, mask, &att);
+ XMapWindow(dd, b1);
+ XMapWindow(dd, b2);
+ XMapWindow(dd, b3);
+
+ gc = XCreateGC(dd, win, 0, &gcv);
+ XSetForeground(dd, gc, att.border_pixel);
+ XSelectInput(dd, win, KeyPressMask | KeyReleaseMask | ExposureMask);
+
+ fh = fs->ascent + fs->descent;
+ mh = ((ww - 20) / 3) - 20;
+
+ /* fixed size... */
+ w = 5 + (((ww - 20 - mh) * 0) / 4);
+ XMoveResizeWindow(dd, b1, w, hh - 15 - fh, mh + 10, fh + 10);
+ XSelectInput(dd, b1,
+ ButtonPressMask | ButtonReleaseMask | ExposureMask);
+ w = 5 + (((ww - 20 - mh) * 1) / 2);
+ XMoveResizeWindow(dd, b2, w, hh - 15 - fh, mh + 10, fh + 10);
+ XSelectInput(dd, b2,
+ ButtonPressMask | ButtonReleaseMask | ExposureMask);
+ w = 5 + (((ww - 20 - mh) * 2) / 2);
+ XMoveResizeWindow(dd, b3, w, hh - 15 - fh, mh + 10, fh + 10);
+ XSelectInput(dd, b3,
+ ButtonPressMask | ButtonReleaseMask | ExposureMask);
+
+ XSync(dd, False);
+ XMapWindow(dd, win);
+ XGrabPointer(dd, win, True, ButtonPressMask | ButtonReleaseMask,
+ GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
+ XGrabKeyboard(dd, win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
+ XSetInputFocus(dd, win, RevertToPointerRoot, CurrentTime);
+ XSync(dd, False);
+
+ button = 0;
+ for (; button == 0;)
+ {
+ XNextEvent(dd, &ev);
+ switch (ev.type)
+ {
+ case KeyPress:
+ key = XKeysymToKeycode(dd, XStringToKeysym("F1"));
+ if (key == ev.xkey.keycode)
+ {
+ button = 1;
+ break;
+ }
+ key = XKeysymToKeycode(dd, XStringToKeysym("F2"));
+ if (key == ev.xkey.keycode)
+ {
+ button = 2;
+ break;
+ }
+ key = XKeysymToKeycode(dd, XStringToKeysym("F3"));
+ if (key == ev.xkey.keycode)
+ {
+ button = 3;
+ break;
+ }
+ break;
+
+ case ButtonPress:
+ if (ev.xbutton.window == b1)
+ button = 1;
+ else if (ev.xbutton.window == b2)
+ button = 2;
+ else if (ev.xbutton.window == b3)
+ button = 3;
+ break;
+
+ case Expose:
+ while (XCheckTypedWindowEvent(dd, ev.xexpose.window, Expose, &ev));
+
+ /* outline */
+ XDrawRectangle(dd, win, gc, 0, 0, ww - 1, hh - 1);
+
+ XDrawRectangle(dd, win, gc, 2, 2, ww - 4 - 1, fh + 4 - 1);
+
+ fw = XTextWidth(fs, title, strlen(title));
+ XDrawString(dd, win, gc, 2 + 2 + ((ww - 4 - 4 - fw) / 2) , 2 + 2 + fs->ascent, title, strlen(title));
+
+ i = 0;
+ j = 0;
+ k = 2 + fh + 4 + 2;
+ while (text[i])
+ {
+ line[j++] = text[i++];
+ if (line[j - 1] == '\n')
+ {
+ line[j - 1] = 0;
+ j = 0;
+ XDrawString(dd, win, gc, 4, k + fs->ascent, line, strlen(line));
+ k += fh + 2;
+ }
+ }
+ fw = XTextWidth(fs, str1, strlen(str1));
+ XDrawRectangle(dd, b1, gc, 0, 0, mh - 1, fh + 10 - 1);
+ XDrawString(dd, b1, gc, 5 + ((mh - fw) / 2), 5 + fs->ascent, str1, strlen(str1));
+
+ fw = XTextWidth(fs, str2, strlen(str2));
+ XDrawRectangle(dd, b2, gc, 0, 0, mh - 1, fh + 10 - 1);
+ XDrawString(dd, b2, gc, 5 + ((mh - fw) / 2), 5 + fs->ascent, str2, strlen(str2));
+
+ fw = XTextWidth(fs, str3, strlen(str3));
+ XDrawRectangle(dd, b3, gc, 0, 0, mh - 1, fh + 10 - 1);
+ XDrawString(dd, b3, gc, 5 + ((mh - fw) / 2), 5 + fs->ascent, str3, strlen(str3));
+
+ XSync(dd, False);
+ break;
+
+ default:
+ break;
+ }
+ }
+ XDestroyWindow(dd, win);
+ XFreeGC(dd, gc);
+ XSync(dd, False);
+
+ switch (button)
+ {
+ case 1:
+ break;
+ case 2:
+ ecore_app_restart();
+ break;
+ case 3:
+ exit(-11);
+ break;
+ default:
+ break;
+ }
+}
+
+/* local subsystem functions */
diff --git a/src/bin/e_alert.h b/src/bin/e_alert.h
new file mode 100644
index 0000000000..7aa76e8e8f
--- /dev/null
+++ b/src/bin/e_alert.h
@@ -0,0 +1,16 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+#ifdef E_TYPEDEFS
+
+#else
+#ifndef E_ALERT_H
+#define E_ALERT_H
+
+int e_alert_init(char *disp);
+int e_alert_shutdown(void);
+
+void e_alert_show(char *text);
+
+#endif
+#endif
diff --git a/src/bin/e_includes.h b/src/bin/e_includes.h
index 8d6034f631..ac85aa2833 100644
--- a/src/bin/e_includes.h
+++ b/src/bin/e_includes.h
@@ -47,3 +47,4 @@
#include "e_datastore.h"
#include "e_msg.h"
#include "e_winlist.h"
+#include "e_alert.h"
diff --git a/src/bin/e_main.c b/src/bin/e_main.c
index c20e9d939e..eb9fd0caa6 100644
--- a/src/bin/e_main.c
+++ b/src/bin/e_main.c
@@ -61,15 +61,30 @@ main(int argc, char **argv)
int after_restart = 0;
char buf[1024];
char *s;
-#if 0
- /* install the signal handlers. */
- struct sigaction sigsegv_action;
-
- sigsegv_action.sa_sigaction = &e_sigseg_act;
- sigsegv_action.sa_flags = 0;
- sigemptyset(&sigsegv_action.sa_mask);
- sigaction(SIGSEGV, &sigsegv_action, NULL);
-#endif
+ struct sigaction action;
+
+ /* trap deadly bug signals and allow some form of sane recovery */
+ /* or ability to gdb attach and debug at this point - better than your */
+ /* wm/desktop vanishing and not knowing what happened */
+ action.sa_sigaction = e_sigseg_act;
+ action.sa_flags = SA_ONSTACK | SA_NODEFER | SA_RESETHAND | SA_ONESHOT | SA_NOMASK | SA_SIGINFO;
+ sigemptyset(&action.sa_mask);
+ sigaction(SIGSEGV, &action, NULL);
+
+ action.sa_sigaction = e_sigill_act;
+ action.sa_flags = SA_ONSTACK | SA_NODEFER | SA_RESETHAND | SA_ONESHOT | SA_NOMASK | SA_SIGINFO;
+ sigemptyset(&action.sa_mask);
+ sigaction(SIGILL, &action, NULL);
+
+ action.sa_sigaction = e_sigfpe_act;
+ action.sa_flags = SA_ONSTACK | SA_NODEFER | SA_RESETHAND | SA_ONESHOT | SA_NOMASK | SA_SIGINFO;
+ sigemptyset(&action.sa_mask);
+ sigaction(SIGFPE, &action, NULL);
+
+ action.sa_sigaction = e_sigbus_act;
+ action.sa_flags = SA_ONSTACK | SA_NODEFER | SA_RESETHAND | SA_ONESHOT | SA_NOMASK | SA_SIGINFO;
+ sigemptyset(&action.sa_mask);
+ sigaction(SIGBUS, &action, NULL);
/* FIXME: this is the init code for letting e be relocatable. right now
* its not used - so i want to see if it can reliably determine its exe
@@ -219,6 +234,14 @@ main(int argc, char **argv)
_e_main_shutdown(-1);
}
_e_main_shutdown_push(_e_main_x_shutdown);
+ /* init x */
+ if (!e_alert_init(NULL))
+ {
+ e_error_message_show(_("Enlightenment cannot initialize its emergency alert system.\n"
+ "Have you set your DISPLAY variable?"));
+ _e_main_shutdown(-1);
+ }
+ _e_main_shutdown_push(e_alert_shutdown);
if (!e_xinerama_init())
{
e_error_message_show(_("Enlightenment cannot setup xinerama wrapping.\n"
@@ -458,7 +481,7 @@ main(int argc, char **argv)
/* run any testing code now we are set up */
e_test();
-
+
/* no longer starting up */
starting = 0;
/* start our main loop */
diff --git a/src/bin/e_signals.c b/src/bin/e_signals.c
index c129ee8644..aef8381885 100644
--- a/src/bin/e_signals.c
+++ b/src/bin/e_signals.c
@@ -22,15 +22,105 @@ e_sigseg_act(int x, siginfo_t *info, void *data)
write(2, "**** Printing Backtrace... *****\n\n", 34);
size = backtrace(array, 255);
backtrace_symbols_fd(array, size, 2);
+ e_alert_show("This is very bad. Enlightenment has segfaulted.\n"
+ "This is not meant to happen and is likely a sign of a\n"
+ "bug in Enlightenment or the libraries it relies on.\n"
+ "\n"
+ "You can gdb attach to this process now to try debug it\n"
+ "or you could exit, or just hit restart to try and get\n"
+ "your desktop back the way it was. This may not always\n"
+ "work perfectly, but it is the bext we can do for now.\n"
+ "\n"
+ "Please help us debug this by compiling Enlightenment and\n"
+ "all its dependency libraries with gdb debugging enabled\n"
+ "and gdb attach to E when this happens and try figure out\n"
+ "what's going on and set us gdb backtraces, variable dumps\n"
+ "etc.");
exit(-11);
}
#else
-void e_sigseg_act(int x, siginfo_t *info, void *data)
+void
+e_sigseg_act(int x, siginfo_t *info, void *data)
{
write(2, "**** SEGMENTATION FAULT ****\n", 29);
- write(2, "**** Backtrace disabled... *****\n\n", 34);
+ e_alert_show("This is very bad. Enlightenment has segfaulted.\n"
+ "This is not meant to happen and is likely a sign of a\n"
+ "bug in Enlightenment or the libraries it relies on.\n"
+ "\n"
+ "You can gdb attach to this process now to try debug it\n"
+ "or you could exit, or just hit restart to try and get\n"
+ "your desktop back the way it was. This may not always\n"
+ "work perfectly, but it is the bext we can do for now.\n"
+ "\n"
+ "Please help us debug this by compiling Enlightenment and\n"
+ "all its dependency libraries with gdb debugging enabled\n"
+ "and gdb attach to E when this happens and try figure out\n"
+ "what's going on and set us gdb backtraces, variable dumps\n"
+ "etc.");
exit(-11);
}
#endif
-
+void
+e_sigill_act(int x, siginfo_t *info, void *data)
+{
+ write(2, "**** ILLEGAL INSTRUCTION ****\n", 30);
+ e_alert_show("This is very bad. Enlightenment has executed and illegal\n"
+ "instruction. This is most likely because Enlightenment or\n"
+ "a library it depends on has been compiled for a CPU type\n"
+ "that you don't have.\n"
+ "\n"
+ "You can gdb attach to this process now to try debug it\n"
+ "or you could exit, or just hit restart to try and get\n"
+ "your desktop back the way it was. This may not always\n"
+ "work perfectly, but it is the bext we can do for now.\n"
+ "\n"
+ "Please help us debug this by compiling Enlightenment and\n"
+ "all its dependency libraries with gdb debugging enabled\n"
+ "and gdb attach to E when this happens and try figure out\n"
+ "what's going on and set us gdb backtraces, variable dumps\n"
+ "etc.");
+ exit(-11);
+}
+
+void
+e_sigfpe_act(int x, siginfo_t *info, void *data)
+{
+ write(2, "**** FLOATING POINT EXCEPTION ****\n", 35);
+ e_alert_show("This is very bad. Enlightenment has recieved a floating\n"
+ "point exception. This is probably due to a divide by 0\n"
+ "in Enlightenment or a library it depends on.\n"
+ "\n"
+ "You can gdb attach to this process now to try debug it\n"
+ "or you could exit, or just hit restart to try and get\n"
+ "your desktop back the way it was. This may not always\n"
+ "work perfectly, but it is the bext we can do for now.\n"
+ "\n"
+ "Please help us debug this by compiling Enlightenment and\n"
+ "all its dependency libraries with gdb debugging enabled\n"
+ "and gdb attach to E when this happens and try figure out\n"
+ "what's going on and set us gdb backtraces, variable dumps\n"
+ "etc.");
+ exit(-11);
+}
+
+void
+e_sigbus_act(int x, siginfo_t *info, void *data)
+{
+ write(2, "**** BUS ERROR ****\n", 21);
+ e_alert_show("This is very bad. Enlightenment has recieved a bus error.\n"
+ "This could be for many reasons - accessing memory not in\n"
+ "its available address space or unable to be paged in.\n"
+ "\n"
+ "You can gdb attach to this process now to try debug it\n"
+ "or you could exit, or just hit restart to try and get\n"
+ "your desktop back the way it was. This may not always\n"
+ "work perfectly, but it is the bext we can do for now.\n"
+ "\n"
+ "Please help us debug this by compiling Enlightenment and\n"
+ "all its dependency libraries with gdb debugging enabled\n"
+ "and gdb attach to E when this happens and try figure out\n"
+ "what's going on and set us gdb backtraces, variable dumps\n"
+ "etc.");
+ exit(-11);
+}
diff --git a/src/bin/e_signals.h b/src/bin/e_signals.h
index bce4c0e162..a34768d7e0 100644
--- a/src/bin/e_signals.h
+++ b/src/bin/e_signals.h
@@ -1,9 +1,16 @@
/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
+#ifdef E_TYPEDEFS
+
+#else
#ifndef E_SIGNALS_H
#define E_SIGNALS_H
-/* signal handler functions for e */
-void e_sigseg_act(int x, siginfo_t *info, void *data);
+EAPI void e_sigseg_act(int x, siginfo_t *info, void *data);
+EAPI void e_sigill_act(int x, siginfo_t *info, void *data);
+EAPI void e_sigfpe_act(int x, siginfo_t *info, void *data);
+EAPI void e_sigbus_act(int x, siginfo_t *info, void *data);
+
+#endif
#endif