blob: b300ef1f862a465af318e5cc8a3f6013d4684d8b [file] [log] [blame]
Victor Stinner024e37a2011-03-31 01:31:06 +02001#include "Python.h"
2#include "pythread.h"
3#include <signal.h>
4#include <object.h>
5#include <frameobject.h>
6#include <signal.h>
7
8#ifdef WITH_THREAD
9# define FAULTHANDLER_LATER
10#endif
11
12#ifndef MS_WINDOWS
Victor Stinnerd727e232011-04-01 12:13:55 +020013 /* register() is useless on Windows, because only SIGSEGV, SIGABRT and
14 SIGILL can be handled by the process, and these signals can only be used
15 with enable(), not using register() */
Victor Stinner024e37a2011-03-31 01:31:06 +020016# define FAULTHANDLER_USER
17#endif
18
Victor Stinnerf0480752011-03-31 11:34:08 +020019/* Allocate at maximum 100 MB of the stack to raise the stack overflow */
20#define STACK_OVERFLOW_MAX_SIZE (100*1024*1024)
21
Victor Stinner024e37a2011-03-31 01:31:06 +020022#define PUTS(fd, str) write(fd, str, strlen(str))
23
24#ifdef HAVE_SIGACTION
25typedef struct sigaction _Py_sighandler_t;
26#else
27typedef PyOS_sighandler_t _Py_sighandler_t;
28#endif
29
30typedef struct {
31 int signum;
32 int enabled;
33 const char* name;
34 _Py_sighandler_t previous;
35 int all_threads;
36} fault_handler_t;
37
38static struct {
39 int enabled;
40 PyObject *file;
41 int fd;
42 int all_threads;
43} fatal_error = {0, NULL, -1, 0};
44
45#ifdef FAULTHANDLER_LATER
46static struct {
47 PyObject *file;
48 int fd;
49 PY_TIMEOUT_T timeout_ms; /* timeout in microseconds */
50 int repeat;
Victor Stinnerf3091342011-04-01 03:16:51 +020051 int running;
Victor Stinner024e37a2011-03-31 01:31:06 +020052 PyInterpreterState *interp;
53 int exit;
54 /* released by parent thread when cancel request */
55 PyThread_type_lock cancel_event;
56 /* released by child thread when joined */
57 PyThread_type_lock join_event;
58} thread;
59#endif
60
61#ifdef FAULTHANDLER_USER
62typedef struct {
63 int enabled;
64 PyObject *file;
65 int fd;
66 int all_threads;
67 _Py_sighandler_t previous;
Victor Stinner44378d42011-04-01 15:37:12 +020068 PyInterpreterState *interp;
Victor Stinner024e37a2011-03-31 01:31:06 +020069} user_signal_t;
70
71static user_signal_t *user_signals;
72
73/* the following macros come from Python: Modules/signalmodule.c */
74#if defined(PYOS_OS2) && !defined(PYCC_GCC)
75#define NSIG 12
76#endif
77#ifndef NSIG
78# if defined(_NSIG)
79# define NSIG _NSIG /* For BSD/SysV */
80# elif defined(_SIGMAX)
81# define NSIG (_SIGMAX + 1) /* For QNX */
82# elif defined(SIGMAX)
83# define NSIG (SIGMAX + 1) /* For djgpp */
84# else
85# define NSIG 64 /* Use a reasonable default value */
86# endif
87#endif
88
89#endif /* FAULTHANDLER_USER */
90
91
92static fault_handler_t faulthandler_handlers[] = {
93#ifdef SIGBUS
94 {SIGBUS, 0, "Bus error", },
95#endif
96#ifdef SIGILL
97 {SIGILL, 0, "Illegal instruction", },
98#endif
99 {SIGFPE, 0, "Floating point exception", },
Victor Stinnerd727e232011-04-01 12:13:55 +0200100 {SIGABRT, 0, "Aborted", },
Victor Stinner024e37a2011-03-31 01:31:06 +0200101 /* define SIGSEGV at the end to make it the default choice if searching the
102 handler fails in faulthandler_fatal_error() */
103 {SIGSEGV, 0, "Segmentation fault", }
104};
105static const unsigned char faulthandler_nsignals = \
106 sizeof(faulthandler_handlers) / sizeof(faulthandler_handlers[0]);
107
108#ifdef HAVE_SIGALTSTACK
109static stack_t stack;
110#endif
111
112
113/* Get the file descriptor of a file by calling its fileno() method and then
114 call its flush() method.
115
116 If file is NULL or Py_None, use sys.stderr as the new file.
117
118 On success, return the new file and write the file descriptor into *p_fd.
119 On error, return NULL. */
120
121static PyObject*
122faulthandler_get_fileno(PyObject *file, int *p_fd)
123{
124 PyObject *result;
125 long fd_long;
126 int fd;
127
128 if (file == NULL || file == Py_None) {
129 file = PySys_GetObject("stderr");
130 if (file == NULL) {
131 PyErr_SetString(PyExc_RuntimeError, "unable to get sys.stderr");
132 return NULL;
133 }
134 }
135
136 result = PyObject_CallMethod(file, "fileno", "");
137 if (result == NULL)
138 return NULL;
139
140 fd = -1;
141 if (PyLong_Check(result)) {
142 fd_long = PyLong_AsLong(result);
143 if (0 <= fd_long && fd_long < INT_MAX)
144 fd = (int)fd_long;
145 }
146 Py_DECREF(result);
147
148 if (fd == -1) {
149 PyErr_SetString(PyExc_RuntimeError,
150 "file.fileno() is not a valid file descriptor");
151 return NULL;
152 }
153
154 result = PyObject_CallMethod(file, "flush", "");
155 if (result != NULL)
156 Py_DECREF(result);
157 else {
158 /* ignore flush() error */
159 PyErr_Clear();
160 }
161 *p_fd = fd;
162 return file;
163}
164
165static PyObject*
166faulthandler_dump_traceback_py(PyObject *self,
167 PyObject *args, PyObject *kwargs)
168{
169 static char *kwlist[] = {"file", "all_threads", NULL};
170 PyObject *file = NULL;
171 int all_threads = 0;
172 PyThreadState *tstate;
173 const char *errmsg;
174 int fd;
175
176 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
177 "|Oi:dump_traceback", kwlist,
178 &file, &all_threads))
179 return NULL;
180
181 file = faulthandler_get_fileno(file, &fd);
182 if (file == NULL)
183 return NULL;
184
185 /* The caller holds the GIL and so PyThreadState_Get() can be used */
186 tstate = PyThreadState_Get();
187 if (tstate == NULL) {
188 PyErr_SetString(PyExc_RuntimeError,
189 "unable to get the current thread state");
190 return NULL;
191 }
192
193 if (all_threads) {
194 errmsg = _Py_DumpTracebackThreads(fd, tstate->interp, tstate);
195 if (errmsg != NULL) {
196 PyErr_SetString(PyExc_RuntimeError, errmsg);
197 return NULL;
198 }
199 }
200 else {
201 _Py_DumpTraceback(fd, tstate);
202 }
203 Py_RETURN_NONE;
204}
205
206
Victor Stinnerd727e232011-04-01 12:13:55 +0200207/* Handler of SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL signals.
Victor Stinner024e37a2011-03-31 01:31:06 +0200208
209 Display the current Python traceback, restore the previous handler and call
210 the previous handler.
211
212 On Windows, don't call explictly the previous handler, because Windows
213 signal handler would not be called (for an unknown reason). The execution of
214 the program continues at faulthandler_fatal_error() exit, but the same
215 instruction will raise the same fault (signal), and so the previous handler
216 will be called.
217
218 This function is signal safe and should only call signal safe functions. */
219
220static void
221faulthandler_fatal_error(
222 int signum
223#ifdef HAVE_SIGACTION
224 , siginfo_t *siginfo, void *ucontext
225#endif
226)
227{
228 const int fd = fatal_error.fd;
229 unsigned int i;
230 fault_handler_t *handler = NULL;
231 PyThreadState *tstate;
232
233 if (!fatal_error.enabled)
234 return;
235
236 for (i=0; i < faulthandler_nsignals; i++) {
237 handler = &faulthandler_handlers[i];
238 if (handler->signum == signum)
239 break;
240 }
241 if (handler == NULL) {
242 /* faulthandler_nsignals == 0 (unlikely) */
243 return;
244 }
245
246 /* restore the previous handler */
247#ifdef HAVE_SIGACTION
248 (void)sigaction(handler->signum, &handler->previous, NULL);
249#else
250 (void)signal(handler->signum, handler->previous);
251#endif
252 handler->enabled = 0;
253
254 PUTS(fd, "Fatal Python error: ");
255 PUTS(fd, handler->name);
256 PUTS(fd, "\n\n");
257
Victor Stinnerd727e232011-04-01 12:13:55 +0200258 /* SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals and
259 so are delivered to the thread that caused the fault. Get the Python
260 thread state of the current thread.
Victor Stinner024e37a2011-03-31 01:31:06 +0200261
262 PyThreadState_Get() doesn't give the state of the thread that caused the
263 fault if the thread released the GIL, and so this function cannot be
264 used. Read the thread local storage (TLS) instead: call
265 PyGILState_GetThisThreadState(). */
266 tstate = PyGILState_GetThisThreadState();
267 if (tstate == NULL)
268 return;
269
270 if (fatal_error.all_threads)
271 _Py_DumpTracebackThreads(fd, tstate->interp, tstate);
272 else
273 _Py_DumpTraceback(fd, tstate);
274
Victor Stinnerbc6a4db2011-04-01 12:08:57 +0200275#ifdef MS_WINDOWS
276 if (signum == SIGSEGV) {
277 /* don't call explictly the previous handler for SIGSEGV in this signal
278 handler, because the Windows signal handler would not be called */
279 return;
280 }
Victor Stinner024e37a2011-03-31 01:31:06 +0200281#endif
Victor Stinnerbc6a4db2011-04-01 12:08:57 +0200282 /* call the previous signal handler: it is called immediatly if we use
283 sigaction() thanks to SA_NODEFER flag, otherwise it is deferred */
284 raise(signum);
Victor Stinner024e37a2011-03-31 01:31:06 +0200285}
286
Victor Stinnerd727e232011-04-01 12:13:55 +0200287/* Install the handler for fatal signals, faulthandler_fatal_error(). */
Victor Stinner024e37a2011-03-31 01:31:06 +0200288
289static PyObject*
290faulthandler_enable(PyObject *self, PyObject *args, PyObject *kwargs)
291{
292 static char *kwlist[] = {"file", "all_threads", NULL};
293 PyObject *file = NULL;
294 int all_threads = 0;
295 unsigned int i;
296 fault_handler_t *handler;
297#ifdef HAVE_SIGACTION
298 struct sigaction action;
299#endif
300 int err;
301 int fd;
302
303 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
304 "|Oi:enable", kwlist, &file, &all_threads))
305 return NULL;
306
307 file = faulthandler_get_fileno(file, &fd);
308 if (file == NULL)
309 return NULL;
310
311 Py_XDECREF(fatal_error.file);
312 Py_INCREF(file);
313 fatal_error.file = file;
314 fatal_error.fd = fd;
315 fatal_error.all_threads = all_threads;
316
317 if (!fatal_error.enabled) {
318 fatal_error.enabled = 1;
319
320 for (i=0; i < faulthandler_nsignals; i++) {
321 handler = &faulthandler_handlers[i];
322#ifdef HAVE_SIGACTION
323 action.sa_sigaction = faulthandler_fatal_error;
324 sigemptyset(&action.sa_mask);
325 /* Do not prevent the signal from being received from within
326 its own signal handler */
327 action.sa_flags = SA_NODEFER;
328#ifdef HAVE_SIGALTSTACK
329 if (stack.ss_sp != NULL) {
330 /* Call the signal handler on an alternate signal stack
331 provided by sigaltstack() */
332 action.sa_flags |= SA_ONSTACK;
333 }
334#endif
335 err = sigaction(handler->signum, &action, &handler->previous);
336#else
337 handler->previous = signal(handler->signum,
338 faulthandler_fatal_error);
339 err = (handler->previous == SIG_ERR);
340#endif
341 if (err) {
342 PyErr_SetFromErrno(PyExc_RuntimeError);
343 return NULL;
344 }
345 handler->enabled = 1;
346 }
347 }
348 Py_RETURN_NONE;
349}
350
351static void
352faulthandler_disable(void)
353{
354 unsigned int i;
355 fault_handler_t *handler;
356
357 if (fatal_error.enabled) {
358 fatal_error.enabled = 0;
359 for (i=0; i < faulthandler_nsignals; i++) {
360 handler = &faulthandler_handlers[i];
361 if (!handler->enabled)
362 continue;
363#ifdef HAVE_SIGACTION
364 (void)sigaction(handler->signum, &handler->previous, NULL);
365#else
366 (void)signal(handler->signum, handler->previous);
367#endif
368 handler->enabled = 0;
369 }
370 }
371
372 Py_CLEAR(fatal_error.file);
373}
374
375static PyObject*
376faulthandler_disable_py(PyObject *self)
377{
378 if (!fatal_error.enabled) {
379 Py_INCREF(Py_False);
380 return Py_False;
381 }
382 faulthandler_disable();
383 Py_INCREF(Py_True);
384 return Py_True;
385}
386
387static PyObject*
388faulthandler_is_enabled(PyObject *self)
389{
390 return PyBool_FromLong(fatal_error.enabled);
391}
392
393#ifdef FAULTHANDLER_LATER
394
395static void
396faulthandler_thread(void *unused)
397{
398 PyLockStatus st;
399 const char* errmsg;
400 PyThreadState *current;
401 int ok;
402
403 do {
404 st = PyThread_acquire_lock_timed(thread.cancel_event,
405 thread.timeout_ms, 0);
406 if (st == PY_LOCK_ACQUIRED) {
407 /* Cancelled by user */
408 break;
409 }
410 /* Timeout => dump traceback */
411 assert(st == PY_LOCK_FAILURE);
412
413 /* get the thread holding the GIL, NULL if no thread hold the GIL */
414 current = _Py_atomic_load_relaxed(&_PyThreadState_Current);
415
416 errmsg = _Py_DumpTracebackThreads(thread.fd, thread.interp, current);
417 ok = (errmsg == NULL);
418
419 if (thread.exit)
420 _exit(1);
421 } while (ok && thread.repeat);
422
423 /* The only way out */
Victor Stinnera4d4f1b2011-04-01 03:00:05 +0200424 PyThread_release_lock(thread.cancel_event);
Victor Stinner024e37a2011-03-31 01:31:06 +0200425 PyThread_release_lock(thread.join_event);
Victor Stinner024e37a2011-03-31 01:31:06 +0200426}
427
428static void
Victor Stinner702624e2011-03-31 03:42:34 +0200429faulthandler_cancel_dump_tracebacks_later(void)
Victor Stinner024e37a2011-03-31 01:31:06 +0200430{
431 if (thread.running) {
432 /* Notify cancellation */
433 PyThread_release_lock(thread.cancel_event);
Victor Stinner024e37a2011-03-31 01:31:06 +0200434 }
Victor Stinnera4d4f1b2011-04-01 03:00:05 +0200435 /* Wait for thread to join */
436 PyThread_acquire_lock(thread.join_event, 1);
Victor Stinnera4d4f1b2011-04-01 03:00:05 +0200437 PyThread_release_lock(thread.join_event);
Victor Stinnerf3091342011-04-01 03:16:51 +0200438 thread.running = 0;
Victor Stinner024e37a2011-03-31 01:31:06 +0200439 Py_CLEAR(thread.file);
440}
441
442static PyObject*
443faulthandler_dump_traceback_later(PyObject *self,
444 PyObject *args, PyObject *kwargs)
445{
446 static char *kwlist[] = {"timeout", "repeat", "file", "exit", NULL};
447 double timeout;
448 PY_TIMEOUT_T timeout_ms;
449 int repeat = 0;
450 PyObject *file = NULL;
451 int fd;
452 int exit = 0;
453
454 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
455 "d|iOi:dump_tracebacks_later", kwlist,
456 &timeout, &repeat, &file, &exit))
457 return NULL;
458 timeout *= 1e6;
459 if (timeout >= (double) PY_TIMEOUT_MAX) {
460 PyErr_SetString(PyExc_OverflowError, "timeout value is too large");
461 return NULL;
462 }
463 timeout_ms = (PY_TIMEOUT_T)timeout;
464 if (timeout_ms <= 0) {
465 PyErr_SetString(PyExc_ValueError, "timeout must be greater than 0");
466 return NULL;
467 }
468
469 file = faulthandler_get_fileno(file, &fd);
470 if (file == NULL)
471 return NULL;
472
473 /* Cancel previous thread, if running */
Victor Stinner702624e2011-03-31 03:42:34 +0200474 faulthandler_cancel_dump_tracebacks_later();
Victor Stinner024e37a2011-03-31 01:31:06 +0200475
476 Py_XDECREF(thread.file);
477 Py_INCREF(file);
478 thread.file = file;
479 thread.fd = fd;
480 thread.timeout_ms = timeout_ms;
481 thread.repeat = repeat;
482 thread.interp = PyThreadState_Get()->interp;
483 thread.exit = exit;
484
485 /* Arm these locks to serve as events when released */
486 PyThread_acquire_lock(thread.join_event, 1);
487 PyThread_acquire_lock(thread.cancel_event, 1);
488
489 thread.running = 1;
490 if (PyThread_start_new_thread(faulthandler_thread, NULL) == -1) {
491 thread.running = 0;
Victor Stinnerf3091342011-04-01 03:16:51 +0200492 PyThread_release_lock(thread.join_event);
493 PyThread_release_lock(thread.cancel_event);
Victor Stinner024e37a2011-03-31 01:31:06 +0200494 Py_CLEAR(thread.file);
495 PyErr_SetString(PyExc_RuntimeError,
496 "unable to start watchdog thread");
497 return NULL;
498 }
499
500 Py_RETURN_NONE;
501}
502
503static PyObject*
Victor Stinner702624e2011-03-31 03:42:34 +0200504faulthandler_cancel_dump_tracebacks_later_py(PyObject *self)
Victor Stinner024e37a2011-03-31 01:31:06 +0200505{
Victor Stinner702624e2011-03-31 03:42:34 +0200506 faulthandler_cancel_dump_tracebacks_later();
Victor Stinner024e37a2011-03-31 01:31:06 +0200507 Py_RETURN_NONE;
508}
509#endif /* FAULTHANDLER_LATER */
510
511#ifdef FAULTHANDLER_USER
512/* Handler of user signals (e.g. SIGUSR1).
513
514 Dump the traceback of the current thread, or of all threads if
515 thread.all_threads is true.
516
517 This function is signal safe and should only call signal safe functions. */
518
519static void
520faulthandler_user(int signum)
521{
522 user_signal_t *user;
523 PyThreadState *tstate;
524
525 user = &user_signals[signum];
526 if (!user->enabled)
527 return;
528
529 /* PyThreadState_Get() doesn't give the state of the current thread if
530 the thread doesn't hold the GIL. Read the thread local storage (TLS)
531 instead: call PyGILState_GetThisThreadState(). */
532 tstate = PyGILState_GetThisThreadState();
Victor Stinner024e37a2011-03-31 01:31:06 +0200533
534 if (user->all_threads)
Victor Stinner44378d42011-04-01 15:37:12 +0200535 _Py_DumpTracebackThreads(user->fd, user->interp, tstate);
536 else {
537 if (tstate == NULL)
538 return;
Victor Stinner024e37a2011-03-31 01:31:06 +0200539 _Py_DumpTraceback(user->fd, tstate);
Victor Stinner44378d42011-04-01 15:37:12 +0200540 }
541}
542
543static int
544check_signum(int signum)
545{
546 unsigned int i;
547
548 for (i=0; i < faulthandler_nsignals; i++) {
549 if (faulthandler_handlers[i].signum == signum) {
550 PyErr_Format(PyExc_RuntimeError,
551 "signal %i cannot be registered, "
552 "use enable() instead",
553 signum);
554 return 0;
555 }
556 }
557 if (signum < 1 || NSIG <= signum) {
558 PyErr_SetString(PyExc_ValueError, "signal number out of range");
559 return 0;
560 }
561 return 1;
Victor Stinner024e37a2011-03-31 01:31:06 +0200562}
563
564static PyObject*
565faulthandler_register(PyObject *self,
566 PyObject *args, PyObject *kwargs)
567{
568 static char *kwlist[] = {"signum", "file", "all_threads", NULL};
569 int signum;
570 PyObject *file = NULL;
571 int all_threads = 0;
572 int fd;
Victor Stinner024e37a2011-03-31 01:31:06 +0200573 user_signal_t *user;
574 _Py_sighandler_t previous;
575#ifdef HAVE_SIGACTION
576 struct sigaction action;
577#endif
Victor Stinner44378d42011-04-01 15:37:12 +0200578 PyThreadState *tstate;
Victor Stinner024e37a2011-03-31 01:31:06 +0200579 int err;
580
581 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
582 "i|Oi:register", kwlist,
583 &signum, &file, &all_threads))
584 return NULL;
585
Victor Stinner44378d42011-04-01 15:37:12 +0200586 if (!check_signum(signum))
Victor Stinner024e37a2011-03-31 01:31:06 +0200587 return NULL;
Victor Stinner024e37a2011-03-31 01:31:06 +0200588
Victor Stinner44378d42011-04-01 15:37:12 +0200589 /* The caller holds the GIL and so PyThreadState_Get() can be used */
590 tstate = PyThreadState_Get();
591 if (tstate == NULL) {
592 PyErr_SetString(PyExc_RuntimeError,
593 "unable to get the current thread state");
594 return NULL;
Victor Stinner024e37a2011-03-31 01:31:06 +0200595 }
596
597 file = faulthandler_get_fileno(file, &fd);
598 if (file == NULL)
599 return NULL;
600
601 if (user_signals == NULL) {
602 user_signals = calloc(NSIG, sizeof(user_signal_t));
603 if (user_signals == NULL)
604 return PyErr_NoMemory();
605 }
606 user = &user_signals[signum];
607
608 if (!user->enabled) {
609#ifdef HAVE_SIGACTION
610 action.sa_handler = faulthandler_user;
611 sigemptyset(&action.sa_mask);
612 /* if the signal is received while the kernel is executing a system
613 call, try to restart the system call instead of interrupting it and
614 return EINTR */
615 action.sa_flags = SA_RESTART;
616#ifdef HAVE_SIGALTSTACK
617 if (stack.ss_sp != NULL) {
618 /* Call the signal handler on an alternate signal stack
619 provided by sigaltstack() */
620 action.sa_flags |= SA_ONSTACK;
621 }
622#endif
623 err = sigaction(signum, &action, &previous);
624#else
625 previous = signal(signum, faulthandler_user);
626 err = (previous == SIG_ERR);
627#endif
628 if (err) {
629 PyErr_SetFromErrno(PyExc_OSError);
630 return NULL;
631 }
632 }
633
634 Py_XDECREF(user->file);
635 Py_INCREF(file);
636 user->file = file;
637 user->fd = fd;
638 user->all_threads = all_threads;
639 user->previous = previous;
Victor Stinner44378d42011-04-01 15:37:12 +0200640 user->interp = tstate->interp;
Victor Stinner024e37a2011-03-31 01:31:06 +0200641 user->enabled = 1;
642
643 Py_RETURN_NONE;
644}
645
646static int
647faulthandler_unregister(user_signal_t *user, int signum)
648{
Victor Stinnera01ca122011-04-01 12:56:17 +0200649 if (!user->enabled)
Victor Stinner024e37a2011-03-31 01:31:06 +0200650 return 0;
651 user->enabled = 0;
652#ifdef HAVE_SIGACTION
653 (void)sigaction(signum, &user->previous, NULL);
654#else
655 (void)signal(signum, user->previous);
656#endif
657 Py_CLEAR(user->file);
658 user->fd = -1;
659 return 1;
660}
661
662static PyObject*
663faulthandler_unregister_py(PyObject *self, PyObject *args)
664{
665 int signum;
666 user_signal_t *user;
667 int change;
668
669 if (!PyArg_ParseTuple(args, "i:unregister", &signum))
670 return NULL;
671
Victor Stinner44378d42011-04-01 15:37:12 +0200672 if (!check_signum(signum))
Victor Stinner024e37a2011-03-31 01:31:06 +0200673 return NULL;
Victor Stinner024e37a2011-03-31 01:31:06 +0200674
675 user = &user_signals[signum];
676 change = faulthandler_unregister(user, signum);
677 return PyBool_FromLong(change);
678}
679#endif /* FAULTHANDLER_USER */
680
681
682static PyObject *
683faulthandler_read_null(PyObject *self, PyObject *args)
684{
685 int *x = NULL, y;
686 int release_gil = 0;
687 if (!PyArg_ParseTuple(args, "|i:_read_null", &release_gil))
688 return NULL;
689 if (release_gil) {
690 Py_BEGIN_ALLOW_THREADS
691 y = *x;
692 Py_END_ALLOW_THREADS
693 } else
694 y = *x;
695 return PyLong_FromLong(y);
696
697}
698
699static PyObject *
700faulthandler_sigsegv(PyObject *self, PyObject *args)
701{
702#if defined(MS_WINDOWS)
Victor Stinnerbc6a4db2011-04-01 12:08:57 +0200703 /* For SIGSEGV, faulthandler_fatal_error() restores the previous signal
704 handler and then gives back the execution flow to the program (without
705 calling explicitly the previous error handler). In a normal case, the
Victor Stinner024e37a2011-03-31 01:31:06 +0200706 SIGSEGV was raised by the kernel because of a fault, and so if the
707 program retries to execute the same instruction, the fault will be
708 raised again.
709
710 Here the fault is simulated by a fake SIGSEGV signal raised by the
711 application. We have to raise SIGSEGV at lease twice: once for
712 faulthandler_fatal_error(), and one more time for the previous signal
713 handler. */
714 while(1)
715 raise(SIGSEGV);
716#else
717 raise(SIGSEGV);
718#endif
719 Py_RETURN_NONE;
720}
721
722static PyObject *
723faulthandler_sigfpe(PyObject *self, PyObject *args)
724{
725 /* Do an integer division by zero: raise a SIGFPE on Intel CPU, but not on
726 PowerPC. Use volatile to disable compile-time optimizations. */
727 volatile int x = 1, y = 0, z;
728 z = x / y;
729 /* if the division by zero didn't raise a SIGFPE, raise it manually */
730 raise(SIGFPE);
731 Py_RETURN_NONE;
732}
733
Victor Stinnerd727e232011-04-01 12:13:55 +0200734static PyObject *
735faulthandler_sigabrt(PyObject *self, PyObject *args)
736{
737#if _MSC_VER
738 /* If Python is compiled in debug mode with Visual Studio, abort() opens
739 a popup asking the user how to handle the assertion. Use raise(SIGABRT)
740 instead. */
741 raise(SIGABRT);
742#else
743 abort();
744#endif
745 Py_RETURN_NONE;
746}
747
Victor Stinner024e37a2011-03-31 01:31:06 +0200748#ifdef SIGBUS
749static PyObject *
750faulthandler_sigbus(PyObject *self, PyObject *args)
751{
752 raise(SIGBUS);
753 Py_RETURN_NONE;
754}
755#endif
756
757#ifdef SIGILL
758static PyObject *
759faulthandler_sigill(PyObject *self, PyObject *args)
760{
Victor Stinner024e37a2011-03-31 01:31:06 +0200761 raise(SIGILL);
Victor Stinner024e37a2011-03-31 01:31:06 +0200762 Py_RETURN_NONE;
763}
764#endif
765
766static PyObject *
767faulthandler_fatal_error_py(PyObject *self, PyObject *args)
768{
769 char *message;
770 if (!PyArg_ParseTuple(args, "y:fatal_error", &message))
771 return NULL;
772 Py_FatalError(message);
773 Py_RETURN_NONE;
774}
775
776#if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)
Victor Stinnerf0480752011-03-31 11:34:08 +0200777void*
778stack_overflow(void *min_sp, void *max_sp, size_t *depth)
Victor Stinner024e37a2011-03-31 01:31:06 +0200779{
780 /* allocate 4096 bytes on the stack at each call */
781 unsigned char buffer[4096];
Victor Stinnerf0480752011-03-31 11:34:08 +0200782 void *sp = &buffer;
783 *depth += 1;
784 if (sp < min_sp || max_sp < sp)
785 return sp;
Victor Stinner024e37a2011-03-31 01:31:06 +0200786 buffer[0] = 1;
Victor Stinnerf0480752011-03-31 11:34:08 +0200787 buffer[4095] = 0;
788 return stack_overflow(min_sp, max_sp, depth);
789}
790
791static PyObject *
792faulthandler_stack_overflow(PyObject *self)
793{
794 size_t depth, size;
795 void *sp = &depth, *stop;
796
797 depth = 0;
798 stop = stack_overflow(sp - STACK_OVERFLOW_MAX_SIZE,
799 sp + STACK_OVERFLOW_MAX_SIZE,
800 &depth);
801 if (sp < stop)
802 size = stop - sp;
803 else
804 size = sp - stop;
805 PyErr_Format(PyExc_RuntimeError,
806 "unable to raise a stack overflow (allocated %zu bytes "
807 "on the stack, %zu recursive calls)",
808 size, depth);
809 return NULL;
Victor Stinner024e37a2011-03-31 01:31:06 +0200810}
811#endif
812
813
814static int
815faulthandler_traverse(PyObject *module, visitproc visit, void *arg)
816{
817#ifdef FAULTHANDLER_USER
818 unsigned int index;
819#endif
820
821#ifdef FAULTHANDLER_LATER
822 Py_VISIT(thread.file);
823#endif
824#ifdef FAULTHANDLER_USER
825 if (user_signals != NULL) {
826 for (index=0; index < NSIG; index++)
827 Py_VISIT(user_signals[index].file);
828 }
829#endif
830 Py_VISIT(fatal_error.file);
831 return 0;
832}
833
834PyDoc_STRVAR(module_doc,
835"faulthandler module.");
836
837static PyMethodDef module_methods[] = {
838 {"enable",
839 (PyCFunction)faulthandler_enable, METH_VARARGS|METH_KEYWORDS,
840 PyDoc_STR("enable(file=sys.stderr, all_threads=False): "
841 "enable the fault handler")},
842 {"disable", (PyCFunction)faulthandler_disable_py, METH_NOARGS,
843 PyDoc_STR("disable(): disable the fault handler")},
844 {"is_enabled", (PyCFunction)faulthandler_is_enabled, METH_NOARGS,
845 PyDoc_STR("is_enabled()->bool: check if the handler is enabled")},
846 {"dump_traceback",
847 (PyCFunction)faulthandler_dump_traceback_py, METH_VARARGS|METH_KEYWORDS,
848 PyDoc_STR("dump_traceback(file=sys.stderr, all_threads=False): "
849 "dump the traceback of the current thread, or of all threads "
850 "if all_threads is True, into file")},
851#ifdef FAULTHANDLER_LATER
852 {"dump_tracebacks_later",
853 (PyCFunction)faulthandler_dump_traceback_later, METH_VARARGS|METH_KEYWORDS,
854 PyDoc_STR("dump_tracebacks_later(timeout, repeat=False, file=sys.stderr):\n"
855 "dump the traceback of all threads in timeout seconds,\n"
856 "or each timeout seconds if repeat is True.")},
857 {"cancel_dump_tracebacks_later",
Victor Stinner702624e2011-03-31 03:42:34 +0200858 (PyCFunction)faulthandler_cancel_dump_tracebacks_later_py, METH_NOARGS,
Victor Stinner024e37a2011-03-31 01:31:06 +0200859 PyDoc_STR("cancel_dump_tracebacks_later():\ncancel the previous call "
860 "to dump_tracebacks_later().")},
861#endif
862
863#ifdef FAULTHANDLER_USER
864 {"register",
865 (PyCFunction)faulthandler_register, METH_VARARGS|METH_KEYWORDS,
866 PyDoc_STR("register(signum, file=sys.stderr, all_threads=False): "
867 "register an handler for the signal 'signum': dump the "
868 "traceback of the current thread, or of all threads if "
869 "all_threads is True, into file")},
870 {"unregister",
871 faulthandler_unregister_py, METH_VARARGS|METH_KEYWORDS,
872 PyDoc_STR("unregister(signum): unregister the handler of the signal "
873 "'signum' registered by register()")},
874#endif
875
876 {"_read_null", faulthandler_read_null, METH_VARARGS,
877 PyDoc_STR("_read_null(release_gil=False): read from NULL, raise "
878 "a SIGSEGV or SIGBUS signal depending on the platform")},
879 {"_sigsegv", faulthandler_sigsegv, METH_VARARGS,
880 PyDoc_STR("_sigsegv(): raise a SIGSEGV signal")},
Victor Stinnerd727e232011-04-01 12:13:55 +0200881 {"_sigabrt", faulthandler_sigabrt, METH_VARARGS,
882 PyDoc_STR("_sigabrt(): raise a SIGABRT signal")},
Victor Stinner024e37a2011-03-31 01:31:06 +0200883 {"_sigfpe", (PyCFunction)faulthandler_sigfpe, METH_NOARGS,
884 PyDoc_STR("_sigfpe(): raise a SIGFPE signal")},
885#ifdef SIGBUS
886 {"_sigbus", (PyCFunction)faulthandler_sigbus, METH_NOARGS,
887 PyDoc_STR("_sigbus(): raise a SIGBUS signal")},
888#endif
889#ifdef SIGILL
890 {"_sigill", (PyCFunction)faulthandler_sigill, METH_NOARGS,
891 PyDoc_STR("_sigill(): raise a SIGILL signal")},
892#endif
893 {"_fatal_error", faulthandler_fatal_error_py, METH_VARARGS,
894 PyDoc_STR("_fatal_error(message): call Py_FatalError(message)")},
895#if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)
896 {"_stack_overflow", (PyCFunction)faulthandler_stack_overflow, METH_NOARGS,
897 PyDoc_STR("_stack_overflow(): recursive call to raise a stack overflow")},
898#endif
899 {NULL, NULL} /* terminator */
900};
901
902static struct PyModuleDef module_def = {
903 PyModuleDef_HEAD_INIT,
904 "faulthandler",
905 module_doc,
906 0, /* non negative size to be able to unload the module */
907 module_methods,
908 NULL,
909 faulthandler_traverse,
910 NULL,
911 NULL
912};
913
914PyMODINIT_FUNC
915PyInit_faulthandler(void)
916{
917 return PyModule_Create(&module_def);
918}
919
920/* Call faulthandler.enable() if PYTHONFAULTHANDLER environment variable is
921 defined, or if sys._xoptions has a 'faulthandler' key. */
922
923static int
924faulthandler_env_options(void)
925{
926 PyObject *xoptions, *key, *module, *res;
927 int enable;
928
929 if (!Py_GETENV("PYTHONFAULTHANDLER")) {
930 xoptions = PySys_GetXOptions();
931 if (xoptions == NULL)
932 return -1;
933
934 key = PyUnicode_FromString("faulthandler");
935 if (key == NULL)
936 return -1;
937
938 enable = PyDict_Contains(xoptions, key);
939 Py_DECREF(key);
940 if (!enable)
941 return 0;
942 }
943 else
944 enable = 1;
945
946 module = PyImport_ImportModule("faulthandler");
947 if (module == NULL) {
948 return -1;
949 }
950 res = PyObject_CallMethod(module, "enable", "");
951 Py_DECREF(module);
952 if (res == NULL)
953 return -1;
954 Py_DECREF(res);
955 return 0;
956}
957
958int _PyFaulthandler_Init(void)
959{
960#ifdef HAVE_SIGALTSTACK
961 int err;
962
963 /* Try to allocate an alternate stack for faulthandler() signal handler to
964 * be able to allocate memory on the stack, even on a stack overflow. If it
965 * fails, ignore the error. */
966 stack.ss_flags = 0;
967 stack.ss_size = SIGSTKSZ;
968 stack.ss_sp = PyMem_Malloc(stack.ss_size);
969 if (stack.ss_sp != NULL) {
970 err = sigaltstack(&stack, NULL);
971 if (err) {
972 PyMem_Free(stack.ss_sp);
973 stack.ss_sp = NULL;
974 }
975 }
976#endif
977#ifdef FAULTHANDLER_LATER
978 thread.running = 0;
979 thread.file = NULL;
980 thread.cancel_event = PyThread_allocate_lock();
981 thread.join_event = PyThread_allocate_lock();
982 if (!thread.cancel_event || !thread.join_event) {
983 PyErr_SetString(PyExc_RuntimeError,
984 "could not allocate locks for faulthandler");
985 return -1;
986 }
987#endif
988
989 return faulthandler_env_options();
990}
991
992void _PyFaulthandler_Fini(void)
993{
994#ifdef FAULTHANDLER_USER
Victor Stinnera01ca122011-04-01 12:56:17 +0200995 unsigned int signum;
Victor Stinner024e37a2011-03-31 01:31:06 +0200996#endif
997
998#ifdef FAULTHANDLER_LATER
999 /* later */
Victor Stinner702624e2011-03-31 03:42:34 +02001000 faulthandler_cancel_dump_tracebacks_later();
Victor Stinner024e37a2011-03-31 01:31:06 +02001001 if (thread.cancel_event) {
1002 PyThread_free_lock(thread.cancel_event);
1003 thread.cancel_event = NULL;
1004 }
1005 if (thread.join_event) {
1006 PyThread_free_lock(thread.join_event);
1007 thread.join_event = NULL;
1008 }
1009#endif
1010
1011#ifdef FAULTHANDLER_USER
1012 /* user */
1013 if (user_signals != NULL) {
Victor Stinnera01ca122011-04-01 12:56:17 +02001014 for (signum=0; signum < NSIG; signum++)
1015 faulthandler_unregister(&user_signals[signum], signum);
Victor Stinner024e37a2011-03-31 01:31:06 +02001016 free(user_signals);
1017 user_signals = NULL;
1018 }
1019#endif
1020
1021 /* fatal */
1022 faulthandler_disable();
1023#ifdef HAVE_SIGALTSTACK
1024 if (stack.ss_sp != NULL) {
1025 PyMem_Free(stack.ss_sp);
1026 stack.ss_sp = NULL;
1027 }
1028#endif
1029}