1/* 2 Unix SMB/CIFS implementation. 3 Critical Fault handling 4 Copyright (C) Andrew Tridgell 1992-1998 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19*/ 20 21#ifdef HAVE_CONFIG_H 22#include "config.h" 23#endif 24 25#include <sys/types.h> 26#ifdef HAVE_UNISTD_H 27#include <unistd.h> 28#endif 29#include <stdio.h> 30#include <stdlib.h> 31#include <string.h> 32#include <signal.h> 33#ifdef HAVE_BACKTRACE_SYMBOLS 34#include <execinfo.h> 35#endif 36#include <atalk/logger.h> 37 38#ifndef SIGNAL_CAST 39#define SIGNAL_CAST (RETSIGTYPE (*)(int)) 40#endif 41#ifndef SAFE_FREE /* Oh no this is also defined in tdb.h */ 42#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0) 43#endif 44#define BACKTRACE_STACK_SIZE 64 45 46static void (*cont_fn)(void *); 47 48/******************************************************************* 49 Catch a signal. This should implement the following semantics: 50 51 1) The handler remains installed after being called. 52 2) The signal should be blocked during handler execution. 53********************************************************************/ 54 55static void (*CatchSignal(int signum,void (*handler)(int )))(int) 56{ 57#ifdef HAVE_SIGACTION 58 struct sigaction act; 59 struct sigaction oldact; 60 61 ZERO_STRUCT(act); 62 63 act.sa_handler = handler; 64#if 0 65 /* 66 * We *want* SIGALRM to interrupt a system call. 67 */ 68 if(signum != SIGALRM) 69 act.sa_flags = SA_RESTART; 70#endif 71 sigemptyset(&act.sa_mask); 72 sigaddset(&act.sa_mask,signum); 73 sigaction(signum,&act,&oldact); 74 return oldact.sa_handler; 75#else /* !HAVE_SIGACTION */ 76 /* FIXME: need to handle sigvec and systems with broken signal() */ 77 return signal(signum, handler); 78#endif 79} 80 81/******************************************************************* 82 Something really nasty happened - panic ! 83********************************************************************/ 84 85void netatalk_panic(const char *why) 86{ 87#ifdef HAVE_BACKTRACE_SYMBOLS 88 void *backtrace_stack[BACKTRACE_STACK_SIZE]; 89 size_t backtrace_size; 90 char **backtrace_strings; 91 92 /* get the backtrace (stack frames) */ 93 backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE); 94 backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size); 95 96 LOG(log_severe, logtype_default, "BACKTRACE: %d stack frames:", backtrace_size); 97 98 if (backtrace_strings) { 99 size_t i; 100 101 for (i = 0; i < backtrace_size; i++) 102 LOG(log_severe, logtype_default, " #%u %s", i, backtrace_strings[i]); 103 104 SAFE_FREE(backtrace_strings); 105 } 106#endif 107} 108 109 110/******************************************************************* 111report a fault 112********************************************************************/ 113static void fault_report(int sig) 114{ 115 static int counter; 116 117 if (counter) 118 abort(); 119 120 counter++; 121 122 LOG(log_severe, logtype_default, "==============================================================="); 123 LOG(log_severe, logtype_default, "INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)getpid(),VERSION); 124 LOG(log_severe, logtype_default, "==============================================================="); 125 126 netatalk_panic("internal error"); 127 128 if (cont_fn) { 129 cont_fn(NULL); 130#ifdef SIGSEGV 131 CatchSignal(SIGSEGV,SIGNAL_CAST SIG_DFL); 132#endif 133#ifdef SIGBUS 134 CatchSignal(SIGBUS,SIGNAL_CAST SIG_DFL); 135#endif 136 return; /* this should cause a core dump */ 137 } 138 abort(); 139} 140 141/**************************************************************************** 142catch serious errors 143****************************************************************************/ 144static void sig_fault(int sig) 145{ 146 fault_report(sig); 147} 148 149/******************************************************************* 150setup our fault handlers 151********************************************************************/ 152void fault_setup(void (*fn)(void *)) 153{ 154 cont_fn = fn; 155 156#ifdef SIGSEGV 157 CatchSignal(SIGSEGV,SIGNAL_CAST sig_fault); 158#endif 159#ifdef SIGBUS 160 CatchSignal(SIGBUS,SIGNAL_CAST sig_fault); 161#endif 162} 163 164