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 #include "system/wait.h"
24 #include "system/filesys.h"
26 /* the registered fault handler */
29 void (*fault_handler
)(int sig
);
32 static const char *progname
;
36 #define BACKTRACE_STACK_SIZE 64
41 void call_backtrace(void)
44 #define BACKTRACE_STACK_SIZE 64
45 void *backtrace_stack
[BACKTRACE_STACK_SIZE
];
46 size_t backtrace_size
;
47 char **backtrace_strings
;
49 /* get the backtrace (stack frames) */
50 backtrace_size
= backtrace(backtrace_stack
,BACKTRACE_STACK_SIZE
);
51 backtrace_strings
= backtrace_symbols(backtrace_stack
, backtrace_size
);
53 DEBUG(0, ("BACKTRACE: %lu stack frames:\n",
54 (unsigned long)backtrace_size
));
56 if (backtrace_strings
) {
59 for (i
= 0; i
< backtrace_size
; i
++)
60 DEBUGADD(0, (" #%u %s\n", i
, backtrace_strings
[i
]));
62 /* Leak the backtrace_strings, rather than risk what free() might do */
67 #define NAMESIZE 32 /* Arbitrary */
69 /* The IRIX libexc library provides an API for unwinding the stack. See
70 * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
71 * since we are about to abort anyway, it hardly matters.
73 * Note that if we paniced due to a SIGSEGV or SIGBUS (or similar) this
74 * will fail with a nasty message upon failing to open the /proc entry.
77 uint64_t addrs
[BACKTRACE_STACK_SIZE
];
78 char * names
[BACKTRACE_STACK_SIZE
];
79 char namebuf
[BACKTRACE_STACK_SIZE
* NAMESIZE
];
88 for (i
= 0; i
< BACKTRACE_STACK_SIZE
; i
++) {
89 names
[i
] = namebuf
+ (i
* NAMESIZE
);
92 levels
= trace_back_stack(0, addrs
, names
,
93 BACKTRACE_STACK_SIZE
, NAMESIZE
);
95 DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels
));
96 for (i
= 0; i
< levels
; i
++) {
97 DEBUGADD(0, (" #%d 0x%llx %s\n", i
, addrs
[i
], names
[i
]));
104 /*******************************************************************
105 Something really nasty happened - panic !
106 ********************************************************************/
107 void smb_panic(const char *why
)
109 const char *cmd
= lp_panic_action();
115 safe_strcpy(cmdstring
, cmd
, sizeof(cmdstring
));
116 snprintf(pidstr
, sizeof(pidstr
), "%u", getpid());
117 all_string_sub(cmdstring
, "%PID%", pidstr
, sizeof(cmdstring
));
119 all_string_sub(cmdstring
, "%PROG%", progname
, sizeof(cmdstring
));
121 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmdstring
));
122 result
= system(cmdstring
);
125 DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
128 DEBUG(0, ("smb_panic(): action returned status %d\n",
129 WEXITSTATUS(result
)));
131 DEBUG(0,("PANIC: %s\n", why
));
136 CatchSignal(SIGABRT
,SIGNAL_CAST SIG_DFL
);
141 /*******************************************************************
143 ********************************************************************/
144 static void fault_report(int sig
)
148 if (counter
) _exit(1);
150 DEBUG(0,("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"));
151 DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig
,(int)getpid(),SAMBA_VERSION_STRING
));
152 DEBUG(0,("\nPlease read the file BUGS.txt in the distribution\n"));
153 DEBUG(0,("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"));
155 smb_panic("internal error");
160 /****************************************************************************
162 ****************************************************************************/
163 static void sig_fault(int sig
)
165 if (fault_handlers
.fault_handler
) {
166 /* we have a fault handler, call it. It may not return. */
167 fault_handlers
.fault_handler(sig
);
169 /* If it returns or doean't exist, use regular reporter */
173 /*******************************************************************
174 setup our fault handlers
175 ********************************************************************/
176 void fault_setup(const char *pname
)
178 if (progname
== NULL
) {
182 CatchSignal(SIGSEGV
,SIGNAL_CAST sig_fault
);
185 CatchSignal(SIGBUS
,SIGNAL_CAST sig_fault
);
188 CatchSignal(SIGABRT
,SIGNAL_CAST sig_fault
);
191 CatchSignal(SIGFPE
,SIGNAL_CAST sig_fault
);
196 register a fault handler.
197 Should only be called once in the execution of smbd.
199 BOOL
register_fault_handler(const char *name
, void (*fault_handler
)(int sig
))
201 if (fault_handlers
.name
!= NULL
) {
202 /* it's already registered! */
203 DEBUG(2,("fault handler '%s' already registered - failed '%s'\n",
204 fault_handlers
.name
, name
));
208 fault_handlers
.name
= name
;
209 fault_handlers
.fault_handler
= fault_handler
;
211 DEBUG(2,("fault handler '%s' registered\n", name
));