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