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 (void (*)(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, "PANIC: %s", why); 97 LOG(log_severe, logtype_default, "BACKTRACE: %d stack frames:", backtrace_size); 98 99 if (backtrace_strings) { 100 size_t i; 101 102 for (i = 0; i < backtrace_size; i++) 103 LOG(log_severe, logtype_default, " #%u %s", i, backtrace_strings[i]); 104 105 SAFE_FREE(backtrace_strings); 106 } 107#endif 108} 109 110 111/******************************************************************* 112report a fault 113********************************************************************/ 114static void fault_report(int sig) 115{ 116 static int counter; 117 118 if (counter) 119 abort(); 120 121 counter++; 122 123 LOG(log_severe, logtype_default, "==============================================================="); 124 LOG(log_severe, logtype_default, "INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)getpid(),VERSION); 125 LOG(log_severe, logtype_default, "==============================================================="); 126 127 netatalk_panic("internal error"); 128 129 if (cont_fn) { 130 cont_fn(NULL); 131#ifdef SIGSEGV 132 CatchSignal(SIGSEGV,SIGNAL_CAST SIG_DFL); 133#endif 134#ifdef SIGBUS 135 CatchSignal(SIGBUS,SIGNAL_CAST SIG_DFL); 136#endif 137 return; /* this should cause a core dump */ 138 } 139 abort(); 140} 141 142/**************************************************************************** 143catch serious errors 144****************************************************************************/ 145static void sig_fault(int sig) 146{ 147 fault_report(sig); 148} 149 150/******************************************************************* 151setup our fault handlers 152********************************************************************/ 153void fault_setup(void (*fn)(void *)) 154{ 155 cont_fn = fn; 156 157#ifdef SIGSEGV 158 CatchSignal(SIGSEGV,SIGNAL_CAST sig_fault); 159#endif 160#ifdef SIGBUS 161 CatchSignal(SIGBUS,SIGNAL_CAST sig_fault); 162#endif 163} 164 165