[d1873c]: src / runtime / interr.c Maximize Restore History

Download this file

interr.c    227 lines (207 with data), 6.4 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/*
* stuff to handle internal errors
*/
/*
* This software is part of the SBCL system. See the README file for
* more information.
*
* This software is derived from the CMU CL system, which was
* written at Carnegie Mellon University and released into the
* public domain. The software is in the public domain and is
* provided with absolutely no warranty. See the COPYING and CREDITS
* files for more information.
*/
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "sbcl.h"
#include "arch.h"
#include "signal.h"
#include "runtime.h"
#include "interr.h"
#include "print.h"
#include "lispregs.h"
#include "genesis/static-symbols.h"
#include "genesis/vector.h"
#include "thread.h"
#include "monitor.h"
/* the way that we shut down the system on a fatal error */
static void
default_lossage_handler(void)
{
exit(1);
}
static void (*lossage_handler)(void) = default_lossage_handler;
void enable_lossage_handler(void)
{
lossage_handler = monitor_or_something;
}
void disable_lossage_handler(void)
{
lossage_handler = default_lossage_handler;
}
static
void print_message(char *fmt, va_list ap)
{
fprintf(stderr, " in SBCL pid %d",getpid());
#if defined(LISP_FEATURE_SB_THREAD)
fprintf(stderr, "(tid %lu)", (unsigned long) thread_self());
#endif
if (fmt) {
fprintf(stderr, ":\n");
vfprintf(stderr, fmt, ap);
}
fprintf(stderr, "\n");
}
static inline void
call_lossage_handler() never_returns;
static inline void
call_lossage_handler()
{
lossage_handler();
fprintf(stderr, "Argh! lossage_handler() returned, total confusion..\n");
exit(1);
}
void
lose(char *fmt, ...)
{
va_list ap;
/* Block signals to prevent other threads, timers and such from
* interfering. If only all threads could be stopped somehow. */
block_blockable_signals();
fprintf(stderr, "fatal error encountered");
va_start(ap, fmt);
print_message(fmt, ap);
va_end(ap);
fprintf(stderr, "\n");
fflush(stderr);
call_lossage_handler();
}
boolean lose_on_corruption_p = 0;
void
corruption_warning_and_maybe_lose(char *fmt, ...)
{
va_list ap;
sigset_t oldset;
thread_sigmask(SIG_BLOCK, &blockable_sigset, &oldset);
fprintf(stderr, "CORRUPTION WARNING");
va_start(ap, fmt);
print_message(fmt, ap);
va_end(ap);
fprintf(stderr, "The integrity of this image is possibly compromised.\n");
if (lose_on_corruption_p)
fprintf(stderr, "Exiting.\n");
else
fprintf(stderr, "Continuing with fingers crossed.\n");
fflush(stderr);
if (lose_on_corruption_p)
call_lossage_handler();
else
thread_sigmask(SIG_SETMASK,&oldset,0);
}
/* internal error handler for when the Lisp error system doesn't exist
*
* FIXME: Shouldn't error output go to stderr instead of stdout? (Alas,
* this'd require changes in a number of things like brief_print(..),
* or I'd have changed it immediately.) */
void
describe_internal_error(os_context_t *context)
{
unsigned char *ptr = arch_internal_error_arguments(context);
int len, scoffset, sc, offset, ch;
len = *ptr++;
printf("internal error #%d\n", *ptr++);
len--;
while (len > 0) {
scoffset = *ptr++;
len--;
if (scoffset == 253) {
scoffset = *ptr++;
len--;
}
else if (scoffset == 254) {
scoffset = ptr[0] + ptr[1]*256;
ptr += 2;
len -= 2;
}
else if (scoffset == 255) {
scoffset = ptr[0] + (ptr[1]<<8) + (ptr[2]<<16) + (ptr[3]<<24);
ptr += 4;
len -= 4;
}
sc = scoffset & 0x1f;
offset = scoffset >> 5;
printf(" SC: %d, Offset: %d", sc, offset);
switch (sc) {
case sc_AnyReg:
case sc_DescriptorReg:
putchar('\t');
brief_print(*os_context_register_addr(context, offset));
break;
case sc_CharacterReg:
ch = *os_context_register_addr(context, offset);
#ifdef LISP_FEATURE_X86
if (offset&1)
ch = ch>>8;
ch = ch & 0xff;
#endif
switch (ch) {
case '\n': printf("\t'\\n'\n"); break;
case '\b': printf("\t'\\b'\n"); break;
case '\t': printf("\t'\\t'\n"); break;
case '\r': printf("\t'\\r'\n"); break;
default:
if (ch < 32 || ch > 127)
printf("\\%03o", ch);
else
printf("\t'%c'\n", ch);
break;
}
break;
case sc_SapReg:
#ifdef sc_WordPointerReg
case sc_WordPointerReg:
#endif
printf("\t0x%08lx\n", (unsigned long) *os_context_register_addr(context, offset));
break;
case sc_SignedReg:
printf("\t%ld\n", (long) *os_context_register_addr(context, offset));
break;
case sc_UnsignedReg:
printf("\t%lu\n", (unsigned long) *os_context_register_addr(context, offset));
break;
#ifdef sc_SingleFloatReg
case sc_SingleFloatReg:
printf("\t%g\n", *(float *)&context->sc_fpregs[offset]);
break;
#endif
#ifdef sc_DoubleFloatReg
case sc_DoubleFloatReg:
printf("\t%g\n", *(double *)&context->sc_fpregs[offset]);
break;
#endif
default:
printf("\t???\n");
break;
}
}
}
/* utility routines used by miscellaneous pieces of code */
lispobj debug_print(lispobj string)
{
/* This is a kludge. It's not actually safe - in general - to use
%primitive print on the alpha, because it skips half of the
number stack setup that should usually be done on a function
call, so the called routine (i.e. this one) ends up being able
to overwrite local variables in the caller. Rather than fix
this everywhere that %primitive print is used (it's only a
debugging aid anyway) we just guarantee our safety by putting
an unused buffer on the stack before doing anything else
here */
char untouched[32];
fprintf(stderr, "%s\n",
(char *)(((struct vector *)native_pointer(string))->data));
/* shut GCC up about not using this, because that's the point.. */
(void)untouched;
return NIL;
}