]> arthur.barton.de Git - netatalk.git/blob - libatalk/util/fault.c
- merge branch-netatalk-afp-3x-dev, HEAD was tagged before
[netatalk.git] / libatalk / util / fault.c
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 #ifdef DEBUG1
26
27 #include <sys/types.h>
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <signal.h>
35 #ifdef HAVE_BACKTRACE_SYMBOLS
36 #include <execinfo.h>
37 #endif
38 #include <atalk/logger.h>
39
40 #ifndef SIGNAL_CAST
41 #define SIGNAL_CAST (RETSIGTYPE (*)(int))
42 #endif
43 #ifndef SAFE_FREE /* Oh no this is also defined in tdb.h */
44 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
45 #endif
46 #define BACKTRACE_STACK_SIZE 64
47
48 static void (*cont_fn)(void *);
49
50 /*******************************************************************
51  Catch a signal. This should implement the following semantics:
52
53  1) The handler remains installed after being called.
54  2) The signal should be blocked during handler execution.
55 ********************************************************************/
56
57 static void (*CatchSignal(int signum,void (*handler)(int )))(int)
58 {
59 #ifdef HAVE_SIGACTION
60         struct sigaction act;
61         struct sigaction oldact;
62
63         ZERO_STRUCT(act);
64
65         act.sa_handler = handler;
66 #if 0 
67         /*
68          * We *want* SIGALRM to interrupt a system call.
69          */
70         if(signum != SIGALRM)
71                 act.sa_flags = SA_RESTART;
72 #endif
73         sigemptyset(&act.sa_mask);
74         sigaddset(&act.sa_mask,signum);
75         sigaction(signum,&act,&oldact);
76         return oldact.sa_handler;
77 #else /* !HAVE_SIGACTION */
78         /* FIXME: need to handle sigvec and systems with broken signal() */
79         return signal(signum, handler);
80 #endif
81 }
82
83 /*******************************************************************
84  Something really nasty happened - panic !
85 ********************************************************************/
86
87 static void smb_panic(const char *why)
88 {
89 #if 0
90         char *cmd;
91         int result;
92 #endif
93 #ifdef HAVE_BACKTRACE_SYMBOLS
94         void *backtrace_stack[BACKTRACE_STACK_SIZE];
95         size_t backtrace_size;
96         char **backtrace_strings;
97 #endif
98
99 #ifdef DEVELOPER
100         {
101                 extern char *global_clobber_region_function;
102                 extern unsigned int global_clobber_region_line;
103
104                 if (global_clobber_region_function) {
105                         DEBUG(0,("smb_panic: clobber_region() last called from [%s(%u)]",
106                                          global_clobber_region_function,
107                                          global_clobber_region_line));
108                 } 
109         }
110 #endif
111
112 #if 0
113         cmd = lp_panic_action();
114         if (cmd && *cmd) {
115                 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
116                 result = system(cmd);
117
118                 if (result == -1)
119                         DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
120                                           strerror(errno)));
121                 else
122                         DEBUG(0, ("smb_panic(): action returned status %d\n",
123                                           WEXITSTATUS(result)));
124         }
125         DEBUG(0,("PANIC: %s\n", why));
126 #endif
127
128 #ifdef HAVE_BACKTRACE_SYMBOLS
129         /* get the backtrace (stack frames) */
130         backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
131         backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
132
133         LOG(log_error, logtype_default, "BACKTRACE: %d stack frames:\n", backtrace_size);
134         
135         if (backtrace_strings) {
136                 size_t i;
137
138                 for (i = 0; i < backtrace_size; i++)
139                         LOG(log_error, logtype_default, " #%u %s", i, backtrace_strings[i]);
140
141                 SAFE_FREE(backtrace_strings);
142         }
143
144 #endif
145
146 }
147
148
149 /*******************************************************************
150 report a fault
151 ********************************************************************/
152 static void fault_report(int sig)
153 {
154         static int counter;
155
156         if (counter) _exit(1);
157
158         counter++;
159
160         LOG(log_error, logtype_default, "===============================================================");
161         LOG(log_error, logtype_default, "INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)getpid(),VERSION);
162         LOG(log_error, logtype_default, "===============================================================");
163   
164         smb_panic("internal error");
165
166         if (cont_fn) {
167                 cont_fn(NULL);
168 #ifdef SIGSEGV
169                 CatchSignal(SIGSEGV,SIGNAL_CAST SIG_DFL);
170 #endif
171 #ifdef SIGBUS
172                 CatchSignal(SIGBUS,SIGNAL_CAST SIG_DFL);
173 #endif
174                 return; /* this should cause a core dump */
175         }
176         exit(1);
177 }
178
179 /****************************************************************************
180 catch serious errors
181 ****************************************************************************/
182 static void sig_fault(int sig)
183 {
184         fault_report(sig);
185 }
186
187 /*******************************************************************
188 setup our fault handlers
189 ********************************************************************/
190 void fault_setup(void (*fn)(void *))
191 {
192         cont_fn = fn;
193
194 #ifdef SIGSEGV
195         CatchSignal(SIGSEGV,SIGNAL_CAST sig_fault);
196 #endif
197 #ifdef SIGBUS
198         CatchSignal(SIGBUS,SIGNAL_CAST sig_fault);
199 #endif
200 }
201
202 #endif