2 Unix SMB/CIFS implementation.
3 Critical Fault handling
4 Copyright (C) Andrew Tridgell 1992-1998
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.
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.
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.
23 static void (*cont_fn)(void *);
25 /* the registered fault handler */
28 void (*fault_handler)(int sig);
34 #define BACKTRACE_STACK_SIZE 64
39 static void call_backtrace(void)
42 #define BACKTRACE_STACK_SIZE 64
43 void *backtrace_stack[BACKTRACE_STACK_SIZE];
44 size_t backtrace_size;
45 char **backtrace_strings;
47 /* get the backtrace (stack frames) */
48 backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
49 backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
51 DEBUG(0, ("BACKTRACE: %lu stack frames:\n",
52 (unsigned long)backtrace_size));
54 if (backtrace_strings) {
57 for (i = 0; i < backtrace_size; i++)
58 DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
60 /* Leak the backtrace_strings, rather than risk what free() might do */
65 #define NAMESIZE 32 /* Arbitrary */
67 /* The IRIX libexc library provides an API for unwinding the stack. See
68 * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
69 * since we are about to abort anyway, it hardly matters.
71 * Note that if we paniced due to a SIGSEGV or SIGBUS (or similar) this
72 * will fail with a nasty message upon failing to open the /proc entry.
75 uint64_t addrs[BACKTRACE_STACK_SIZE];
76 char * names[BACKTRACE_STACK_SIZE];
77 char namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
86 for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
87 names[i] = namebuf + (i * NAMESIZE);
90 levels = trace_back_stack(0, addrs, names,
91 BACKTRACE_STACK_SIZE, NAMESIZE);
93 DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
94 for (i = 0; i < levels; i++) {
95 DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
102 /*******************************************************************
103 Something really nasty happened - panic !
104 ********************************************************************/
105 void smb_panic(const char *why)
107 const char *cmd = lp_panic_action();
111 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
112 result = system(cmd);
115 DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
118 DEBUG(0, ("smb_panic(): action returned status %d\n",
119 WEXITSTATUS(result)));
121 DEBUG(0,("PANIC: %s\n", why));
126 CatchSignal(SIGABRT,SIGNAL_CAST SIG_DFL);
131 /*******************************************************************
133 ********************************************************************/
134 static void fault_report(int sig)
138 if (counter) _exit(1);
140 DEBUG(0,("===============================================================\n"));
141 DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)getpid(),SAMBA_VERSION_STRING));
142 DEBUG(0,("\nPlease read the file BUGS.txt in the distribution\n"));
143 DEBUG(0,("===============================================================\n"));
145 smb_panic("internal error");
150 CatchSignal(SIGSEGV,SIGNAL_CAST SIG_DFL);
153 CatchSignal(SIGBUS,SIGNAL_CAST SIG_DFL);
156 CatchSignal(SIGABRT,SIGNAL_CAST SIG_DFL);
158 return; /* this should cause a core dump */
163 /****************************************************************************
165 ****************************************************************************/
166 static void sig_fault(int sig)
168 if (fault_handlers.fault_handler) {
169 /* we have a fault handler, call it. It may not return. */
170 fault_handlers.fault_handler(sig);
172 /* If it returns or doean't exist, use regular reporter */
176 /*******************************************************************
177 setup our fault handlers
178 ********************************************************************/
179 void fault_setup(void (*fn)(void *))
184 CatchSignal(SIGSEGV,SIGNAL_CAST sig_fault);
187 CatchSignal(SIGBUS,SIGNAL_CAST sig_fault);
190 CatchSignal(SIGABRT,SIGNAL_CAST sig_fault);
195 register a fault handler.
196 Should only be called once in the execution of smbd.
198 BOOL register_fault_handler(const char *name, void (*fault_handler)(int sig))
200 if (fault_handlers.name != NULL) {
201 /* it's already registered! */
202 DEBUG(2,("fault handler '%s' already registered - failed '%s'\n",
203 fault_handlers.name, name));
207 fault_handlers.name = name;
208 fault_handlers.fault_handler = fault_handler;
210 DEBUG(2,("fault handler '%s' registered\n", name));