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