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 3 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, see <http://www.gnu.org/licenses/>.
22
#include "system/wait.h"
23
#include "system/filesys.h"
27
* @brief Fault handling
30
/* the registered fault handler */
33
void (*fault_handler)(int sig);
36
static const char *progname;
45
* Write backtrace to debug log
47
_PUBLIC_ void call_backtrace(void)
50
#ifndef BACKTRACE_STACK_SIZE
51
#define BACKTRACE_STACK_SIZE 64
53
void *backtrace_stack[BACKTRACE_STACK_SIZE];
54
size_t backtrace_size;
55
char **backtrace_strings;
57
/* get the backtrace (stack frames) */
58
backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
59
backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
61
DEBUG(0, ("BACKTRACE: %lu stack frames:\n",
62
(unsigned long)backtrace_size));
64
if (backtrace_strings) {
67
for (i = 0; i < backtrace_size; i++)
68
DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
70
/* Leak the backtrace_strings, rather than risk what free() might do */
75
#define NAMESIZE 32 /* Arbitrary */
76
#ifndef BACKTRACE_STACK_SIZE
77
#define BACKTRACE_STACK_SIZE 64
80
/* The IRIX libexc library provides an API for unwinding the stack. See
81
* libexc(3) for details. Apparantly trace_back_stack leaks memory, but
82
* since we are about to abort anyway, it hardly matters.
84
* Note that if we paniced due to a SIGSEGV or SIGBUS (or similar) this
85
* will fail with a nasty message upon failing to open the /proc entry.
88
uint64_t addrs[BACKTRACE_STACK_SIZE];
89
char * names[BACKTRACE_STACK_SIZE];
90
char namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
99
for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
100
names[i] = namebuf + (i * NAMESIZE);
103
levels = trace_back_stack(0, addrs, names,
104
BACKTRACE_STACK_SIZE, NAMESIZE);
106
DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
107
for (i = 0; i < levels; i++) {
108
DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
115
_PUBLIC_ const char *panic_action = NULL;
118
Something really nasty happened - panic !
120
_PUBLIC_ _NORETURN_ void smb_panic(const char *why)
124
if (panic_action && *panic_action) {
127
safe_strcpy(cmdstring, panic_action, sizeof(cmdstring));
128
snprintf(pidstr, sizeof(pidstr), "%u", getpid());
129
all_string_sub(cmdstring, "%PID%", pidstr, sizeof(cmdstring));
131
all_string_sub(cmdstring, "%PROG%", progname, sizeof(cmdstring));
133
DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmdstring));
134
result = system(cmdstring);
137
DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
140
DEBUG(0, ("smb_panic(): action returned status %d\n",
141
WEXITSTATUS(result)));
143
DEBUG(0,("PANIC: %s\n", why));
148
CatchSignal(SIGABRT,SIGNAL_CAST SIG_DFL);
156
_NORETURN_ static void fault_report(int sig)
160
if (counter) _exit(1);
162
DEBUG(0,("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"));
163
DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)getpid(),SAMBA_VERSION_STRING));
164
DEBUG(0,("\nPlease read the file BUGS.txt in the distribution\n"));
165
DEBUG(0,("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"));
167
smb_panic("internal error");
175
_NORETURN_ static void sig_fault(int sig)
177
if (fault_handlers.fault_handler) {
178
/* we have a fault handler, call it. It may not return. */
179
fault_handlers.fault_handler(sig);
181
/* If it returns or doesn't exist, use regular reporter */
186
setup our fault handlers
188
_PUBLIC_ void fault_setup(const char *pname)
190
if (progname == NULL) {
194
CatchSignal(SIGSEGV,SIGNAL_CAST sig_fault);
197
CatchSignal(SIGBUS,SIGNAL_CAST sig_fault);
200
CatchSignal(SIGABRT,SIGNAL_CAST sig_fault);
203
CatchSignal(SIGFPE,SIGNAL_CAST sig_fault);
208
register a fault handler.
209
Should only be called once in the execution of smbd.
211
_PUBLIC_ bool register_fault_handler(const char *name,
212
void (*fault_handler)(int sig))
214
if (fault_handlers.name != NULL) {
215
/* it's already registered! */
216
DEBUG(2,("fault handler '%s' already registered - failed '%s'\n",
217
fault_handlers.name, name));
221
fault_handlers.name = name;
222
fault_handlers.fault_handler = fault_handler;
224
DEBUG(2,("fault handler '%s' registered\n", name));