From aaa88bb0e48b54faf527d409a5075e4789f429d0 Mon Sep 17 00:00:00 2001 From: Ettore Perazzoli Date: Thu, 13 Feb 2003 21:11:58 +0000 Subject: (segv_redirect): New, SIGSEGV signal handler. (setup_segv_redirect): New function to set it up. (main): Call setup_segv_redirect(). svn path=/trunk/; revision=19907 --- shell/ChangeLog | 8 ++++++++ shell/main.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/shell/ChangeLog b/shell/ChangeLog index 756fc95aa5..69104e466b 100644 --- a/shell/ChangeLog +++ b/shell/ChangeLog @@ -1,3 +1,11 @@ +2003-02-13 Ettore Perazzoli + + [Ported SIGSEGV signal redirection hack from mail/.] + + * main.c (segv_redirect): New, SIGSEGV signal handler. + (setup_segv_redirect): New function to set it up. + (main): Call setup_segv_redirect(). + 2003-02-12 Ettore Perazzoli * e-setup.c (DEFAULT_USER_PATH): Look into evolution/$BASE_VERSION diff --git a/shell/main.c b/shell/main.c index ee929abdea..f766a668ab 100644 --- a/shell/main.c +++ b/shell/main.c @@ -66,11 +66,14 @@ #include #include +#include #include #include #include #include +#include + static EShell *shell = NULL; static char *evolution_directory = NULL; @@ -438,6 +441,58 @@ idle_cb (void *data) return FALSE; } + +/* SIGSEGV handling. + + The GNOME SEGV handler will lose if it's not run from the main Gtk + thread. So if we have to redirect the signal if the crash happens in another + thread. */ + +static void (*gnome_segv_handler) (int); +static GStaticMutex segv_mutex = G_STATIC_MUTEX_INIT; +static pthread_t main_thread; + +static void +segv_redirect (int sig) +{ + if (pthread_self () == main_thread) + gnome_segv_handler (sig); + else { + pthread_kill (main_thread, sig); + + /* We can't return from the signal handler or the thread may + SEGV again. But we can't pthread_exit, because then the + thread may get cleaned up before bug-buddy can get a stack + trace. So we block by trying to lock a mutex we know is + already locked. */ + g_static_mutex_lock (&segv_mutex); + } +} + +static void +setup_segv_redirect (void) +{ + struct sigaction sa, osa; + + sigaction (SIGSEGV, NULL, &osa); + if (osa.sa_handler == SIG_DFL) + return; + + main_thread = pthread_self (); + + sa.sa_flags = 0; + sigemptyset (&sa.sa_mask); + sa.sa_handler = segv_redirect; + sigaction (SIGSEGV, &sa, NULL); + sigaction (SIGBUS, &sa, NULL); + sigaction (SIGFPE, &sa, NULL); + + sa.sa_handler = SIG_IGN; + sigaction (SIGXFSZ, &sa, NULL); + gnome_segv_handler = osa.sa_handler; + g_static_mutex_lock (&segv_mutex); +} + int main (int argc, char **argv) { @@ -480,6 +535,8 @@ main (int argc, char **argv) exit (1); } + setup_segv_redirect (); + if (evolution_debug_log) { int fd; -- cgit v1.2.3