2 (c) Copyright 2001-2008 The world wide DirectFB Open Source Community (directfb.org)
3 (c) Copyright 2000-2004 Convergence (integrated media) GmbH
7 Written by Denis Oliver Kropp <dok@directfb.org>,
8 Andreas Hundt <andi@fischlustig.de>,
9 Sven Neumann <neo@directfb.org>,
10 Ville Syrjälä <syrjala@sci.fi> and
11 Claudio Ciccani <klan@users.sf.net>.
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 2 of the License, or (at your option) any later version.
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, write to the
25 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 Boston, MA 02111-1307, USA.
39 #include <direct/clock.h>
40 #include <direct/conf.h>
41 #include <direct/debug.h>
42 #include <direct/list.h>
43 #include <direct/mem.h>
44 #include <direct/messages.h>
45 #include <direct/signals.h>
46 #include <direct/system.h>
47 #include <direct/trace.h>
48 #include <direct/util.h>
50 D_DEBUG_DOMAIN( Direct_Signals, "Direct/Signals", "Signal handling" );
53 struct __D_DirectSignalHandler {
59 DirectSignalHandlerFunc func;
63 /**************************************************************************************************/
67 struct sigaction old_action;
70 static int sigs_to_handle[] = { /*SIGALRM,*/ SIGHUP, SIGINT, /*SIGPIPE,*/ /*SIGPOLL,*/
71 SIGTERM, /*SIGUSR1, SIGUSR2,*/ /*SIGVTALRM,*/
72 /*SIGSTKFLT,*/ SIGABRT, SIGFPE, SIGILL, SIGQUIT,
73 SIGSEGV, SIGTRAP, /*SIGSYS, SIGEMT,*/ SIGBUS,
76 #define NUM_SIGS_TO_HANDLE ((int)D_ARRAY_SIZE( sigs_to_handle ))
78 static SigHandled sigs_handled[NUM_SIGS_TO_HANDLE];
80 static DirectLink *handlers = NULL;
81 static pthread_mutex_t handlers_lock;
83 /**************************************************************************************************/
85 static void install_handlers();
86 static void remove_handlers();
88 /**************************************************************************************************/
91 direct_signals_initialize()
93 D_DEBUG_AT( Direct_Signals, "Initializing...\n" );
95 direct_util_recursive_pthread_mutex_init( &handlers_lock );
103 direct_signals_shutdown()
105 D_DEBUG_AT( Direct_Signals, "Shutting down...\n" );
109 pthread_mutex_destroy( &handlers_lock );
115 direct_signals_block_all()
119 D_DEBUG_AT( Direct_Signals, "Blocking all signals from now on!\n" );
121 sigfillset( &signals );
123 if (pthread_sigmask( SIG_BLOCK, &signals, NULL ))
124 D_PERROR( "Direct/Signals: Setting signal mask failed!\n" );
128 direct_signal_handler_add( int num,
129 DirectSignalHandlerFunc func,
131 DirectSignalHandler **ret_handler )
133 DirectSignalHandler *handler;
135 D_ASSERT( func != NULL );
136 D_ASSERT( ret_handler != NULL );
138 D_DEBUG_AT( Direct_Signals,
139 "Adding handler %p for signal %d with context %p...\n", func, num, ctx );
141 handler = D_CALLOC( 1, sizeof(DirectSignalHandler) );
143 D_WARN( "out of memory" );
144 return DR_NOLOCALMEMORY;
148 handler->func = func;
151 D_MAGIC_SET( handler, DirectSignalHandler );
153 pthread_mutex_lock( &handlers_lock );
154 direct_list_append( &handlers, &handler->link );
155 pthread_mutex_unlock( &handlers_lock );
157 *ret_handler = handler;
163 direct_signal_handler_remove( DirectSignalHandler *handler )
165 D_MAGIC_ASSERT( handler, DirectSignalHandler );
167 D_DEBUG_AT( Direct_Signals, "Removing handler %p for signal %d with context %p...\n",
168 handler->func, handler->num, handler->ctx );
170 pthread_mutex_lock( &handlers_lock );
171 direct_list_remove( &handlers, &handler->link );
172 pthread_mutex_unlock( &handlers_lock );
174 D_MAGIC_CLEAR( handler );
181 /**************************************************************************************************/
184 show_segv( const siginfo_t *info )
186 switch (info->si_code) {
189 direct_log_printf( NULL, " (at %p, invalid address) <--\n", info->si_addr );
194 direct_log_printf( NULL, " (at %p, invalid permissions) <--\n", info->si_addr );
202 show_bus( const siginfo_t *info )
204 switch (info->si_code) {
207 direct_log_printf( NULL, " (at %p, invalid address alignment) <--\n", info->si_addr );
212 direct_log_printf( NULL, " (at %p, non-existent physical address) <--\n", info->si_addr );
217 direct_log_printf( NULL, " (at %p, object specific hardware error) <--\n", info->si_addr );
226 show_ill( const siginfo_t *info )
228 switch (info->si_code) {
231 direct_log_printf( NULL, " (at %p, illegal opcode) <--\n", info->si_addr );
236 direct_log_printf( NULL, " (at %p, illegal operand) <--\n", info->si_addr );
241 direct_log_printf( NULL, " (at %p, illegal addressing mode) <--\n", info->si_addr );
246 direct_log_printf( NULL, " (at %p, illegal trap) <--\n", info->si_addr );
251 direct_log_printf( NULL, " (at %p, privileged opcode) <--\n", info->si_addr );
256 direct_log_printf( NULL, " (at %p, privileged register) <--\n", info->si_addr );
261 direct_log_printf( NULL, " (at %p, coprocessor error) <--\n", info->si_addr );
266 direct_log_printf( NULL, " (at %p, internal stack error) <--\n", info->si_addr );
275 show_fpe( const siginfo_t *info )
277 switch (info->si_code) {
280 direct_log_printf( NULL, " (at %p, integer divide by zero) <--\n", info->si_addr );
285 direct_log_printf( NULL, " (at %p, floating point divide by zero) <--\n", info->si_addr );
290 direct_log_printf( NULL, " (at %p) <--\n", info->si_addr );
296 show_any( const siginfo_t *info )
298 switch (info->si_code) {
301 direct_log_printf( NULL, " (sent by pid %d, uid %d) <--\n", info->si_pid, info->si_uid );
306 direct_log_printf( NULL, " (sent by the kernel) <--\n" );
315 signal_handler( int num, siginfo_t *info, void *foo )
317 signal_handler( int num )
322 int pid = direct_gettid();
323 long long millis = direct_clock_get_millis();
328 direct_log_printf( NULL, "(!) [%5d: %4lld.%03lld] --> Caught signal %d",
329 pid, millis/1000, millis%1000, num );
332 if (info && info > (siginfo_t*) 0x100) {
335 if (info->si_code > 0 && info->si_code < 0x80) {
336 addr = info->si_addr;
340 shown = show_segv( info );
344 shown = show_bus( info );
348 shown = show_ill( info );
352 shown = show_fpe( info );
356 direct_log_printf( NULL, " <--\n" );
363 shown = show_any( info );
366 direct_log_printf( NULL, " (unknown origin) <--\n" );
370 direct_log_printf( NULL, ", no siginfo available <--\n" );
372 direct_trace_print_stacks();
374 /* Loop through all handlers. */
375 pthread_mutex_lock( &handlers_lock );
377 direct_list_foreach_safe (l, n, handlers) {
378 DirectSignalHandler *handler = (DirectSignalHandler*) l;
380 if (handler->num != num && handler->num != DIRECT_SIGNAL_ANY)
383 switch (handler->func( num, addr, handler->ctx )) {
388 direct_list_remove( &handlers, &handler->link );
389 D_MAGIC_CLEAR( handler );
394 millis = direct_clock_get_millis();
396 direct_log_printf( NULL, "(!) [%5d: %4lld.%03lld] -> cured!\n",
397 pid, millis / 1000, millis % 1000 );
398 pthread_mutex_unlock( &handlers_lock );
402 D_BUG( "unknown result" );
407 pthread_mutex_unlock( &handlers_lock );
418 /**************************************************************************************************/
425 for (i=0; i<NUM_SIGS_TO_HANDLE; i++) {
426 sigs_handled[i].signum = -1;
428 if (direct_config->sighandler && !sigismember( &direct_config->dont_catch,
431 struct sigaction action;
432 int signum = sigs_to_handle[i];
435 action.sa_sigaction = signal_handler;
436 action.sa_flags = SA_SIGINFO;
438 action.sa_handler = signal_handler;
442 if (signum != SIGSEGV)
443 action.sa_flags |= SA_NODEFER;
445 sigemptyset( &action.sa_mask );
447 if (sigaction( signum, &action, &sigs_handled[i].old_action )) {
448 D_PERROR( "Direct/Signals: "
449 "Unable to install signal handler for signal %d!\n", signum );
453 sigs_handled[i].signum = signum;
463 for (i=0; i<NUM_SIGS_TO_HANDLE; i++) {
464 if (sigs_handled[i].signum != -1) {
465 int signum = sigs_handled[i].signum;
467 if (sigaction( signum, &sigs_handled[i].old_action, NULL )) {
468 D_PERROR( "Direct/Signals: "
469 "Unable to restore previous handler for signal %d!\n", signum );
472 sigs_handled[i].signum = -1;