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