segv/bus/ill/fpe handler to trap all the nasties and allow debug or recovery

SVN revision: 15329
This commit is contained in:
Carsten Haitzler 2005-06-15 05:06:45 +00:00
parent 33323d7f3a
commit 2ed41fb21f
8 changed files with 391 additions and 18 deletions

1
TODO
View File

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

View File

@ -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 \

234
src/bin/e_alert.c Normal file
View File

@ -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 */

16
src/bin/e_alert.h Normal file
View File

@ -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

View File

@ -47,3 +47,4 @@
#include "e_datastore.h"
#include "e_msg.h"
#include "e_winlist.h"
#include "e_alert.h"

View File

@ -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;
struct sigaction action;
sigsegv_action.sa_sigaction = &e_sigseg_act;
sigsegv_action.sa_flags = 0;
sigemptyset(&sigsegv_action.sa_mask);
sigaction(SIGSEGV, &sigsegv_action, NULL);
#endif
/* 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"

View File

@ -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);
}

View File

@ -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