From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/lib/direct/signals.c | 480 +++++++++++++++++++++++++++++++++++ 1 file changed, 480 insertions(+) create mode 100755 Source/DirectFB/lib/direct/signals.c (limited to 'Source/DirectFB/lib/direct/signals.c') diff --git a/Source/DirectFB/lib/direct/signals.c b/Source/DirectFB/lib/direct/signals.c new file mode 100755 index 0000000..5b0310a --- /dev/null +++ b/Source/DirectFB/lib/direct/signals.c @@ -0,0 +1,480 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +D_DEBUG_DOMAIN( Direct_Signals, "Direct/Signals", "Signal handling" ); + + +struct __D_DirectSignalHandler { + DirectLink link; + + int magic; + + int num; + DirectSignalHandlerFunc func; + void *ctx; +}; + +/**************************************************************************************************/ + +typedef struct { + int signum; + struct sigaction old_action; +} SigHandled; + +static int sigs_to_handle[] = { /*SIGALRM,*/ SIGHUP, SIGINT, /*SIGPIPE,*/ /*SIGPOLL,*/ + SIGTERM, /*SIGUSR1, SIGUSR2,*/ /*SIGVTALRM,*/ + /*SIGSTKFLT,*/ SIGABRT, SIGFPE, SIGILL, SIGQUIT, + SIGSEGV, SIGTRAP, /*SIGSYS, SIGEMT,*/ SIGBUS, + SIGXCPU, SIGXFSZ }; + +#define NUM_SIGS_TO_HANDLE ((int)D_ARRAY_SIZE( sigs_to_handle )) + +static SigHandled sigs_handled[NUM_SIGS_TO_HANDLE]; + +static DirectLink *handlers = NULL; +static pthread_mutex_t handlers_lock; + +/**************************************************************************************************/ + +static void install_handlers( void ); +static void remove_handlers( void ); + +/**************************************************************************************************/ + +DirectResult +direct_signals_initialize( void ) +{ + D_DEBUG_AT( Direct_Signals, "Initializing...\n" ); + + direct_util_recursive_pthread_mutex_init( &handlers_lock ); + + install_handlers(); + + return DR_OK; +} + +DirectResult +direct_signals_shutdown( void ) +{ + D_DEBUG_AT( Direct_Signals, "Shutting down...\n" ); + + remove_handlers(); + + pthread_mutex_destroy( &handlers_lock ); + + return DR_OK; +} + +void +direct_signals_block_all( void ) +{ + sigset_t signals; + + D_DEBUG_AT( Direct_Signals, "Blocking all signals from now on!\n" ); + + sigfillset( &signals ); + + if (pthread_sigmask( SIG_BLOCK, &signals, NULL )) + D_PERROR( "Direct/Signals: Setting signal mask failed!\n" ); +} + +DirectResult +direct_signal_handler_add( int num, + DirectSignalHandlerFunc func, + void *ctx, + DirectSignalHandler **ret_handler ) +{ + DirectSignalHandler *handler; + + D_ASSERT( func != NULL ); + D_ASSERT( ret_handler != NULL ); + + D_DEBUG_AT( Direct_Signals, + "Adding handler %p for signal %d with context %p...\n", func, num, ctx ); + + handler = D_CALLOC( 1, sizeof(DirectSignalHandler) ); + if (!handler) { + D_WARN( "out of memory" ); + return DR_NOLOCALMEMORY; + } + + handler->num = num; + handler->func = func; + handler->ctx = ctx; + + D_MAGIC_SET( handler, DirectSignalHandler ); + + pthread_mutex_lock( &handlers_lock ); + direct_list_append( &handlers, &handler->link ); + pthread_mutex_unlock( &handlers_lock ); + + *ret_handler = handler; + + return DR_OK; +} + +DirectResult +direct_signal_handler_remove( DirectSignalHandler *handler ) +{ + D_MAGIC_ASSERT( handler, DirectSignalHandler ); + + D_DEBUG_AT( Direct_Signals, "Removing handler %p for signal %d with context %p...\n", + handler->func, handler->num, handler->ctx ); + + pthread_mutex_lock( &handlers_lock ); + direct_list_remove( &handlers, &handler->link ); + pthread_mutex_unlock( &handlers_lock ); + + D_MAGIC_CLEAR( handler ); + + D_FREE( handler ); + + return DR_OK; +} + +/**************************************************************************************************/ + +static bool +show_segv( const siginfo_t *info ) +{ + switch (info->si_code) { +#ifdef SEGV_MAPERR + case SEGV_MAPERR: + direct_log_printf( NULL, " (at %p, invalid address) <--\n", info->si_addr ); + return true; +#endif +#ifdef SEGV_ACCERR + case SEGV_ACCERR: + direct_log_printf( NULL, " (at %p, invalid permissions) <--\n", info->si_addr ); + return true; +#endif + } + return false; +} + +static bool +show_bus( const siginfo_t *info ) +{ + switch (info->si_code) { +#ifdef BUG_ADRALN + case BUS_ADRALN: + direct_log_printf( NULL, " (at %p, invalid address alignment) <--\n", info->si_addr ); + return true; +#endif +#ifdef BUS_ADRERR + case BUS_ADRERR: + direct_log_printf( NULL, " (at %p, non-existent physical address) <--\n", info->si_addr ); + return true; +#endif +#ifdef BUS_OBJERR + case BUS_OBJERR: + direct_log_printf( NULL, " (at %p, object specific hardware error) <--\n", info->si_addr ); + return true; +#endif + } + + return false; +} + +static bool +show_ill( const siginfo_t *info ) +{ + switch (info->si_code) { +#ifdef ILL_ILLOPC + case ILL_ILLOPC: + direct_log_printf( NULL, " (at %p, illegal opcode) <--\n", info->si_addr ); + return true; +#endif +#ifdef ILL_ILLOPN + case ILL_ILLOPN: + direct_log_printf( NULL, " (at %p, illegal operand) <--\n", info->si_addr ); + return true; +#endif +#ifdef ILL_ILLADR + case ILL_ILLADR: + direct_log_printf( NULL, " (at %p, illegal addressing mode) <--\n", info->si_addr ); + return true; +#endif +#ifdef ILL_ILLTRP + case ILL_ILLTRP: + direct_log_printf( NULL, " (at %p, illegal trap) <--\n", info->si_addr ); + return true; +#endif +#ifdef ILL_PRVOPC + case ILL_PRVOPC: + direct_log_printf( NULL, " (at %p, privileged opcode) <--\n", info->si_addr ); + return true; +#endif +#ifdef ILL_PRVREG + case ILL_PRVREG: + direct_log_printf( NULL, " (at %p, privileged register) <--\n", info->si_addr ); + return true; +#endif +#ifdef ILL_COPROC + case ILL_COPROC: + direct_log_printf( NULL, " (at %p, coprocessor error) <--\n", info->si_addr ); + return true; +#endif +#ifdef ILL_BADSTK + case ILL_BADSTK: + direct_log_printf( NULL, " (at %p, internal stack error) <--\n", info->si_addr ); + return true; +#endif + } + + return false; +} + +static bool +show_fpe( const siginfo_t *info ) +{ + switch (info->si_code) { +#ifdef FPE_INTDIV + case FPE_INTDIV: + direct_log_printf( NULL, " (at %p, integer divide by zero) <--\n", info->si_addr ); + return true; +#endif +#ifdef FPE_FLTDIV + case FPE_FLTDIV: + direct_log_printf( NULL, " (at %p, floating point divide by zero) <--\n", info->si_addr ); + return true; +#endif + } + + direct_log_printf( NULL, " (at %p) <--\n", info->si_addr ); + + return true; +} + +static bool +show_any( const siginfo_t *info ) +{ + switch (info->si_code) { +#ifdef SI_USER + case SI_USER: + direct_log_printf( NULL, " (sent by pid %d, uid %d) <--\n", info->si_pid, info->si_uid ); + return true; +#endif +#ifdef SI_KERNEL + case SI_KERNEL: + direct_log_printf( NULL, " (sent by the kernel) <--\n" ); + return true; +#endif + } + return false; +} + +static void +#ifdef SA_SIGINFO +signal_handler( int num, siginfo_t *info, void *foo ) +#else +signal_handler( int num ) +#endif +{ + DirectLink *l, *n; + void *addr = NULL; + int pid = direct_gettid(); + long long millis = direct_clock_get_millis(); + + fflush(stdout); + fflush(stderr); + + direct_log_printf( NULL, "(!) [%5d: %4lld.%03lld] --> Caught signal %d", + pid, millis/1000, millis%1000, num ); + +#ifdef SA_SIGINFO + if (info && info > (siginfo_t*) 0x100) { + bool shown = false; + + if (info->si_code > 0 && info->si_code < 0x80) { + addr = info->si_addr; + + switch (num) { + case SIGSEGV: + shown = show_segv( info ); + break; + + case SIGBUS: + shown = show_bus( info ); + break; + + case SIGILL: + shown = show_ill( info ); + break; + + case SIGFPE: + shown = show_fpe( info ); + break; + + default: + direct_log_printf( NULL, " <--\n" ); + addr = NULL; + shown = true; + break; + } + } + else + shown = show_any( info ); + + if (!shown) + direct_log_printf( NULL, " (unknown origin) <--\n" ); + } + else +#endif + direct_log_printf( NULL, ", no siginfo available <--\n" ); + + direct_trace_print_stacks(); + + /* Loop through all handlers. */ + pthread_mutex_lock( &handlers_lock ); + + direct_list_foreach_safe (l, n, handlers) { + DirectSignalHandler *handler = (DirectSignalHandler*) l; + + if (handler->num != num && handler->num != DIRECT_SIGNAL_ANY) + continue; + + switch (handler->func( num, addr, handler->ctx )) { + case DSHR_OK: + break; + + case DSHR_REMOVE: + direct_list_remove( &handlers, &handler->link ); + D_MAGIC_CLEAR( handler ); + D_FREE( handler ); + break; + + case DSHR_RESUME: + millis = direct_clock_get_millis(); + + direct_log_printf( NULL, "(!) [%5d: %4lld.%03lld] -> cured!\n", + pid, millis / 1000, millis % 1000 ); + pthread_mutex_unlock( &handlers_lock ); + return; + + default: + D_BUG( "unknown result" ); + break; + } + } + + pthread_mutex_unlock( &handlers_lock ); + + +// sleep(100); + + + remove_handlers(); + + raise( num ); + + abort(); + + exit( -num ); +} + +/**************************************************************************************************/ + +static void +install_handlers( void ) +{ + int i; + + for (i=0; isighandler && !sigismember( &direct_config->dont_catch, + sigs_to_handle[i] )) + { + struct sigaction action; + int signum = sigs_to_handle[i]; + +#ifdef SA_SIGINFO + action.sa_sigaction = signal_handler; + action.sa_flags = SA_SIGINFO; +#else + action.sa_handler = signal_handler; + action.sa_flags = 0; +#endif + + if (signum != SIGSEGV) + action.sa_flags |= SA_NODEFER; + + sigemptyset( &action.sa_mask ); + + if (sigaction( signum, &action, &sigs_handled[i].old_action )) { + D_PERROR( "Direct/Signals: " + "Unable to install signal handler for signal %d!\n", signum ); + continue; + } + + sigs_handled[i].signum = signum; + } + } +} + +static void +remove_handlers( void ) +{ + int i; + + for (i=0; i