diff options
author | Carsten Haitzler <raster@rasterman.com> | 2005-06-15 05:06:45 +0000 |
---|---|---|
committer | Carsten Haitzler <raster@rasterman.com> | 2005-06-15 05:06:45 +0000 |
commit | 2ed41fb21f128fc6c6a16df4dbf5b589a4a6c837 (patch) | |
tree | 2a424f50d0e19a6f929243999ce677c8d62b2891 | |
parent | 33323d7f3ae2ae9943c3cf854fce6a81536c557e (diff) | |
download | enlightenment-2ed41fb21f128fc6c6a16df4dbf5b589a4a6c837.tar.gz |
segv/bus/ill/fpe handler to trap all the nasties and allow debug or recovery
SVN revision: 15329
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | src/bin/Makefile.am | 7 | ||||
-rw-r--r-- | src/bin/e_alert.c | 234 | ||||
-rw-r--r-- | src/bin/e_alert.h | 16 | ||||
-rw-r--r-- | src/bin/e_includes.h | 1 | ||||
-rw-r--r-- | src/bin/e_main.c | 43 | ||||
-rw-r--r-- | src/bin/e_signals.c | 96 | ||||
-rw-r--r-- | src/bin/e_signals.h | 11 |
8 files changed, 391 insertions, 18 deletions
@@ -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 |