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