enlightenment/src/bin/e_signals.c

175 lines
4.3 KiB
C

/*
* NOTE TO FreeBSD users. Install libexecinfo from
* ports/devel/libexecinfo and add -lexecinfo to LDFLAGS
* to add backtrace support.
*/
#include "e.h"
#ifdef HAVE_EXECINFO_H
# include <execinfo.h>
#endif
static volatile Eina_Bool _e_x_composite_shutdown_try = 0;
static void
_e_x_composite_shutdown(void)
{
// Ecore_X_Display *dpy;
Ecore_X_Window root;
if (_e_x_composite_shutdown_try) return; /* we failed :-( */
_e_x_composite_shutdown_try = 1;
// dpy = ecore_x_display_get();
root = ecore_x_window_root_first_get();
/* ignore errors, we really don't care at this point */
ecore_x_composite_unredirect_subwindows(root, ECORE_X_COMPOSITE_UPDATE_MANUAL);
_e_x_composite_shutdown_try = 0;
}
#define _e_write_safe(fd, buf) _e_write_safe_int(fd, buf, sizeof(buf))
static void
_e_write_safe_int(int fd, const char *buf, size_t size)
{
while (size > 0)
{
ssize_t done = write(fd, buf, size);
if (done >= 0)
{
buf += done;
size -= done;
}
else
{
if ((errno == EAGAIN) || (errno == EINTR))
continue;
else
{
perror("write");
return;
}
}
}
}
static void
_e_gdb_print_backtrace(int fd)
{
char cmd[1024];
size_t size;
int ret;
// FIXME: we are in a segv'd state. do as few function calls and things
// depending on a known working state as possible. this also prevents the
// white box allowing recovery or deeper gdbing, thus until this works
// properly, it's disabled (properly means always reliable, always
// printf bt and allows e to continue and pop up box, perferably allowing
// debugging in the gui etc. etc.
return;
if (getenv("E_NO_GDB_BACKTRACE"))
return;
size = snprintf(cmd, sizeof(cmd),
"gdb --pid=%d "
"-ex 'thread apply all bt' "
"-ex detach -ex quit", getpid());
if (size >= sizeof(cmd))
return;
_e_write_safe(fd, "EXECUTING GDB AS: ");
_e_write_safe_int(fd, cmd, size);
_e_write_safe(fd, "\n");
ret = system(cmd); // TODO: use popen() or fork()+pipe()+exec() and save to 'fd'
}
#define _e_backtrace(msg) _e_backtrace_int(2, msg, sizeof(msg))
static void
_e_backtrace_int(int fd, const char *msg, size_t msg_len)
{
char attachmsg[1024];
void *array[255];
size_t size;
return; // disable. causes hangs and problems
_e_write_safe_int(fd, msg, msg_len);
_e_write_safe(fd, "\nBEGIN TRACEBACK\n");
size = backtrace(array, 255);
backtrace_symbols_fd(array, size, fd);
_e_write_safe(fd, "END TRACEBACK\n");
size = snprintf(attachmsg, sizeof(attachmsg),
"debug with: gdb --pid=%d\n", getpid());
if (size < sizeof(attachmsg))
_e_write_safe_int(fd, attachmsg, size);
_e_gdb_print_backtrace(fd);
}
/* a tricky little devil, requires e and it's libs to be built
* with the -rdynamic flag to GCC for any sort of decent output.
*/
EAPI void
e_sigseg_act(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__)
{
_e_backtrace("**** SEGMENTATION FAULT ****");
_e_x_composite_shutdown();
ecore_x_pointer_ungrab();
ecore_x_keyboard_ungrab();
ecore_x_ungrab();
ecore_x_sync();
e_alert_show(SIGSEGV);
}
EAPI void
e_sigill_act(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__)
{
_e_backtrace("**** ILLEGAL INSTRUCTION ****");
_e_x_composite_shutdown();
ecore_x_pointer_ungrab();
ecore_x_keyboard_ungrab();
ecore_x_ungrab();
ecore_x_sync();
e_alert_show(SIGILL);
}
EAPI void
e_sigfpe_act(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__)
{
_e_backtrace("**** FLOATING POINT EXCEPTION ****");
_e_x_composite_shutdown();
ecore_x_pointer_ungrab();
ecore_x_keyboard_ungrab();
ecore_x_ungrab();
ecore_x_sync();
e_alert_show(SIGFPE);
}
EAPI void
e_sigbus_act(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__)
{
_e_backtrace("**** BUS ERROR ****");
_e_x_composite_shutdown();
ecore_x_pointer_ungrab();
ecore_x_keyboard_ungrab();
ecore_x_ungrab();
ecore_x_sync();
e_alert_show(SIGBUS);
}
EAPI void
e_sigabrt_act(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__)
{
_e_backtrace("**** ABORT ****");
_e_x_composite_shutdown();
ecore_x_pointer_ungrab();
ecore_x_keyboard_ungrab();
ecore_x_ungrab();
ecore_x_sync();
e_alert_show(SIGABRT);
}