blob: 6e3ed7c51b6381278b912b16109794a841d97f70 [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
273#ifndef MS_WINDOWS
274 /* call the previous signal handler: it is called if we use sigaction()
275 thanks to SA_NODEFER flag, otherwise it is deferred */
276 raise(signum);
277#else
278 /* on Windows, don't call explictly the previous handler, because Windows
279 signal handler would not be called */
280#endif
281}
282
283/* Install handler for fatal signals (SIGSEGV, SIGFPE, ...). */
284
285static PyObject*
286faulthandler_enable(PyObject *self, PyObject *args, PyObject *kwargs)
287{
288 static char *kwlist[] = {"file", "all_threads", NULL};
289 PyObject *file = NULL;
290 int all_threads = 0;
291 unsigned int i;
292 fault_handler_t *handler;
293#ifdef HAVE_SIGACTION
294 struct sigaction action;
295#endif
296 int err;
297 int fd;
298
299 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
300 "|Oi:enable", kwlist, &file, &all_threads))
301 return NULL;
302
303 file = faulthandler_get_fileno(file, &fd);
304 if (file == NULL)
305 return NULL;
306
307 Py_XDECREF(fatal_error.file);
308 Py_INCREF(file);
309 fatal_error.file = file;
310 fatal_error.fd = fd;
311 fatal_error.all_threads = all_threads;
312
313 if (!fatal_error.enabled) {
314 fatal_error.enabled = 1;
315
316 for (i=0; i < faulthandler_nsignals; i++) {
317 handler = &faulthandler_handlers[i];
318#ifdef HAVE_SIGACTION
319 action.sa_sigaction = faulthandler_fatal_error;
320 sigemptyset(&action.sa_mask);
321 /* Do not prevent the signal from being received from within
322 its own signal handler */
323 action.sa_flags = SA_NODEFER;
324#ifdef HAVE_SIGALTSTACK
325 if (stack.ss_sp != NULL) {
326 /* Call the signal handler on an alternate signal stack
327 provided by sigaltstack() */
328 action.sa_flags |= SA_ONSTACK;
329 }
330#endif
331 err = sigaction(handler->signum, &action, &handler->previous);
332#else
333 handler->previous = signal(handler->signum,
334 faulthandler_fatal_error);
335 err = (handler->previous == SIG_ERR);
336#endif
337 if (err) {
338 PyErr_SetFromErrno(PyExc_RuntimeError);
339 return NULL;
340 }
341 handler->enabled = 1;
342 }
343 }
344 Py_RETURN_NONE;
345}
346
347static void
348faulthandler_disable(void)
349{
350 unsigned int i;
351 fault_handler_t *handler;
352
353 if (fatal_error.enabled) {
354 fatal_error.enabled = 0;
355 for (i=0; i < faulthandler_nsignals; i++) {
356 handler = &faulthandler_handlers[i];
357 if (!handler->enabled)
358 continue;
359#ifdef HAVE_SIGACTION
360 (void)sigaction(handler->signum, &handler->previous, NULL);
361#else
362 (void)signal(handler->signum, handler->previous);
363#endif
364 handler->enabled = 0;
365 }
366 }
367
368 Py_CLEAR(fatal_error.file);
369}
370
371static PyObject*
372faulthandler_disable_py(PyObject *self)
373{
374 if (!fatal_error.enabled) {
375 Py_INCREF(Py_False);
376 return Py_False;
377 }
378 faulthandler_disable();
379 Py_INCREF(Py_True);
380 return Py_True;
381}
382
383static PyObject*
384faulthandler_is_enabled(PyObject *self)
385{
386 return PyBool_FromLong(fatal_error.enabled);
387}
388
389#ifdef FAULTHANDLER_LATER
390
391static void
392faulthandler_thread(void *unused)
393{
394 PyLockStatus st;
395 const char* errmsg;
396 PyThreadState *current;
397 int ok;
398
399 do {
400 st = PyThread_acquire_lock_timed(thread.cancel_event,
401 thread.timeout_ms, 0);
402 if (st == PY_LOCK_ACQUIRED) {
403 /* Cancelled by user */
404 break;
405 }
406 /* Timeout => dump traceback */
407 assert(st == PY_LOCK_FAILURE);
408
409 /* get the thread holding the GIL, NULL if no thread hold the GIL */
410 current = _Py_atomic_load_relaxed(&_PyThreadState_Current);
411
412 errmsg = _Py_DumpTracebackThreads(thread.fd, thread.interp, current);
413 ok = (errmsg == NULL);
414
415 if (thread.exit)
416 _exit(1);
417 } while (ok && thread.repeat);
418
419 /* The only way out */
Victor Stinnera4d4f1b2011-04-01 03:00:05 +0200420 PyThread_release_lock(thread.cancel_event);
Victor Stinner024e37a2011-03-31 01:31:06 +0200421 PyThread_release_lock(thread.join_event);
Victor Stinner024e37a2011-03-31 01:31:06 +0200422}
423
424static void
Victor Stinner702624e2011-03-31 03:42:34 +0200425faulthandler_cancel_dump_tracebacks_later(void)
Victor Stinner024e37a2011-03-31 01:31:06 +0200426{
427 if (thread.running) {
428 /* Notify cancellation */
429 PyThread_release_lock(thread.cancel_event);
Victor Stinner024e37a2011-03-31 01:31:06 +0200430 }
Victor Stinnera4d4f1b2011-04-01 03:00:05 +0200431 /* Wait for thread to join */
432 PyThread_acquire_lock(thread.join_event, 1);
Victor Stinnera4d4f1b2011-04-01 03:00:05 +0200433 PyThread_release_lock(thread.join_event);
Victor Stinnerf3091342011-04-01 03:16:51 +0200434 thread.running = 0;
Victor Stinner024e37a2011-03-31 01:31:06 +0200435 Py_CLEAR(thread.file);
436}
437
438static PyObject*
439faulthandler_dump_traceback_later(PyObject *self,
440 PyObject *args, PyObject *kwargs)
441{
442 static char *kwlist[] = {"timeout", "repeat", "file", "exit", NULL};
443 double timeout;
444 PY_TIMEOUT_T timeout_ms;
445 int repeat = 0;
446 PyObject *file = NULL;
447 int fd;
448 int exit = 0;
449
450 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
451 "d|iOi:dump_tracebacks_later", kwlist,
452 &timeout, &repeat, &file, &exit))
453 return NULL;
454 timeout *= 1e6;
455 if (timeout >= (double) PY_TIMEOUT_MAX) {
456 PyErr_SetString(PyExc_OverflowError, "timeout value is too large");
457 return NULL;
458 }
459 timeout_ms = (PY_TIMEOUT_T)timeout;
460 if (timeout_ms <= 0) {
461 PyErr_SetString(PyExc_ValueError, "timeout must be greater than 0");
462 return NULL;
463 }
464
465 file = faulthandler_get_fileno(file, &fd);
466 if (file == NULL)
467 return NULL;
468
469 /* Cancel previous thread, if running */
Victor Stinner702624e2011-03-31 03:42:34 +0200470 faulthandler_cancel_dump_tracebacks_later();
Victor Stinner024e37a2011-03-31 01:31:06 +0200471
472 Py_XDECREF(thread.file);
473 Py_INCREF(file);
474 thread.file = file;
475 thread.fd = fd;
476 thread.timeout_ms = timeout_ms;
477 thread.repeat = repeat;
478 thread.interp = PyThreadState_Get()->interp;
479 thread.exit = exit;
480
481 /* Arm these locks to serve as events when released */
482 PyThread_acquire_lock(thread.join_event, 1);
483 PyThread_acquire_lock(thread.cancel_event, 1);
484
485 thread.running = 1;
486 if (PyThread_start_new_thread(faulthandler_thread, NULL) == -1) {
487 thread.running = 0;
Victor Stinnerf3091342011-04-01 03:16:51 +0200488 PyThread_release_lock(thread.join_event);
489 PyThread_release_lock(thread.cancel_event);
Victor Stinner024e37a2011-03-31 01:31:06 +0200490 Py_CLEAR(thread.file);
491 PyErr_SetString(PyExc_RuntimeError,
492 "unable to start watchdog thread");
493 return NULL;
494 }
495
496 Py_RETURN_NONE;
497}
498
499static PyObject*
Victor Stinner702624e2011-03-31 03:42:34 +0200500faulthandler_cancel_dump_tracebacks_later_py(PyObject *self)
Victor Stinner024e37a2011-03-31 01:31:06 +0200501{
Victor Stinner702624e2011-03-31 03:42:34 +0200502 faulthandler_cancel_dump_tracebacks_later();
Victor Stinner024e37a2011-03-31 01:31:06 +0200503 Py_RETURN_NONE;
504}
505#endif /* FAULTHANDLER_LATER */
506
507#ifdef FAULTHANDLER_USER
508/* Handler of user signals (e.g. SIGUSR1).
509
510 Dump the traceback of the current thread, or of all threads if
511 thread.all_threads is true.
512
513 This function is signal safe and should only call signal safe functions. */
514
515static void
516faulthandler_user(int signum)
517{
518 user_signal_t *user;
519 PyThreadState *tstate;
520
521 user = &user_signals[signum];
522 if (!user->enabled)
523 return;
524
525 /* PyThreadState_Get() doesn't give the state of the current thread if
526 the thread doesn't hold the GIL. Read the thread local storage (TLS)
527 instead: call PyGILState_GetThisThreadState(). */
528 tstate = PyGILState_GetThisThreadState();
529 if (tstate == NULL) {
530 /* unable to get the current thread, do nothing */
531 return;
532 }
533
534 if (user->all_threads)
535 _Py_DumpTracebackThreads(user->fd, tstate->interp, tstate);
536 else
537 _Py_DumpTraceback(user->fd, tstate);
538}
539
540static PyObject*
541faulthandler_register(PyObject *self,
542 PyObject *args, PyObject *kwargs)
543{
544 static char *kwlist[] = {"signum", "file", "all_threads", NULL};
545 int signum;
546 PyObject *file = NULL;
547 int all_threads = 0;
548 int fd;
549 unsigned int i;
550 user_signal_t *user;
551 _Py_sighandler_t previous;
552#ifdef HAVE_SIGACTION
553 struct sigaction action;
554#endif
555 int err;
556
557 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
558 "i|Oi:register", kwlist,
559 &signum, &file, &all_threads))
560 return NULL;
561
562 if (signum < 1 || NSIG <= signum) {
563 PyErr_SetString(PyExc_ValueError, "signal number out of range");
564 return NULL;
565 }
566
567 for (i=0; i < faulthandler_nsignals; i++) {
568 if (faulthandler_handlers[i].signum == signum) {
569 PyErr_Format(PyExc_RuntimeError,
570 "signal %i cannot be registered by register(), "
571 "use enable() instead",
572 signum);
573 return NULL;
574 }
575 }
576
577 file = faulthandler_get_fileno(file, &fd);
578 if (file == NULL)
579 return NULL;
580
581 if (user_signals == NULL) {
582 user_signals = calloc(NSIG, sizeof(user_signal_t));
583 if (user_signals == NULL)
584 return PyErr_NoMemory();
585 }
586 user = &user_signals[signum];
587
588 if (!user->enabled) {
589#ifdef HAVE_SIGACTION
590 action.sa_handler = faulthandler_user;
591 sigemptyset(&action.sa_mask);
592 /* if the signal is received while the kernel is executing a system
593 call, try to restart the system call instead of interrupting it and
594 return EINTR */
595 action.sa_flags = SA_RESTART;
596#ifdef HAVE_SIGALTSTACK
597 if (stack.ss_sp != NULL) {
598 /* Call the signal handler on an alternate signal stack
599 provided by sigaltstack() */
600 action.sa_flags |= SA_ONSTACK;
601 }
602#endif
603 err = sigaction(signum, &action, &previous);
604#else
605 previous = signal(signum, faulthandler_user);
606 err = (previous == SIG_ERR);
607#endif
608 if (err) {
609 PyErr_SetFromErrno(PyExc_OSError);
610 return NULL;
611 }
612 }
613
614 Py_XDECREF(user->file);
615 Py_INCREF(file);
616 user->file = file;
617 user->fd = fd;
618 user->all_threads = all_threads;
619 user->previous = previous;
620 user->enabled = 1;
621
622 Py_RETURN_NONE;
623}
624
625static int
626faulthandler_unregister(user_signal_t *user, int signum)
627{
628 if (user->enabled)
629 return 0;
630 user->enabled = 0;
631#ifdef HAVE_SIGACTION
632 (void)sigaction(signum, &user->previous, NULL);
633#else
634 (void)signal(signum, user->previous);
635#endif
636 Py_CLEAR(user->file);
637 user->fd = -1;
638 return 1;
639}
640
641static PyObject*
642faulthandler_unregister_py(PyObject *self, PyObject *args)
643{
644 int signum;
645 user_signal_t *user;
646 int change;
647
648 if (!PyArg_ParseTuple(args, "i:unregister", &signum))
649 return NULL;
650
651 if (signum < 1 || NSIG <= signum) {
652 PyErr_SetString(PyExc_ValueError, "signal number out of range");
653 return NULL;
654 }
655
656 user = &user_signals[signum];
657 change = faulthandler_unregister(user, signum);
658 return PyBool_FromLong(change);
659}
660#endif /* FAULTHANDLER_USER */
661
662
663static PyObject *
664faulthandler_read_null(PyObject *self, PyObject *args)
665{
666 int *x = NULL, y;
667 int release_gil = 0;
668 if (!PyArg_ParseTuple(args, "|i:_read_null", &release_gil))
669 return NULL;
670 if (release_gil) {
671 Py_BEGIN_ALLOW_THREADS
672 y = *x;
673 Py_END_ALLOW_THREADS
674 } else
675 y = *x;
676 return PyLong_FromLong(y);
677
678}
679
680static PyObject *
681faulthandler_sigsegv(PyObject *self, PyObject *args)
682{
683#if defined(MS_WINDOWS)
684 /* faulthandler_fatal_error() restores the previous signal handler and then
685 gives back the execution flow to the program. In a normal case, the
686 SIGSEGV was raised by the kernel because of a fault, and so if the
687 program retries to execute the same instruction, the fault will be
688 raised again.
689
690 Here the fault is simulated by a fake SIGSEGV signal raised by the
691 application. We have to raise SIGSEGV at lease twice: once for
692 faulthandler_fatal_error(), and one more time for the previous signal
693 handler. */
694 while(1)
695 raise(SIGSEGV);
696#else
697 raise(SIGSEGV);
698#endif
699 Py_RETURN_NONE;
700}
701
702static PyObject *
703faulthandler_sigfpe(PyObject *self, PyObject *args)
704{
705 /* Do an integer division by zero: raise a SIGFPE on Intel CPU, but not on
706 PowerPC. Use volatile to disable compile-time optimizations. */
707 volatile int x = 1, y = 0, z;
708 z = x / y;
709 /* if the division by zero didn't raise a SIGFPE, raise it manually */
710 raise(SIGFPE);
711 Py_RETURN_NONE;
712}
713
714#ifdef SIGBUS
715static PyObject *
716faulthandler_sigbus(PyObject *self, PyObject *args)
717{
718 raise(SIGBUS);
719 Py_RETURN_NONE;
720}
721#endif
722
723#ifdef SIGILL
724static PyObject *
725faulthandler_sigill(PyObject *self, PyObject *args)
726{
727#if defined(MS_WINDOWS)
728 /* see faulthandler_sigsegv() for the explanation about while(1) */
729 while(1)
730 raise(SIGILL);
731#else
732 raise(SIGILL);
733#endif
734 Py_RETURN_NONE;
735}
736#endif
737
738static PyObject *
739faulthandler_fatal_error_py(PyObject *self, PyObject *args)
740{
741 char *message;
742 if (!PyArg_ParseTuple(args, "y:fatal_error", &message))
743 return NULL;
744 Py_FatalError(message);
745 Py_RETURN_NONE;
746}
747
748#if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)
Victor Stinnerf0480752011-03-31 11:34:08 +0200749void*
750stack_overflow(void *min_sp, void *max_sp, size_t *depth)
Victor Stinner024e37a2011-03-31 01:31:06 +0200751{
752 /* allocate 4096 bytes on the stack at each call */
753 unsigned char buffer[4096];
Victor Stinnerf0480752011-03-31 11:34:08 +0200754 void *sp = &buffer;
755 *depth += 1;
756 if (sp < min_sp || max_sp < sp)
757 return sp;
Victor Stinner024e37a2011-03-31 01:31:06 +0200758 buffer[0] = 1;
Victor Stinnerf0480752011-03-31 11:34:08 +0200759 buffer[4095] = 0;
760 return stack_overflow(min_sp, max_sp, depth);
761}
762
763static PyObject *
764faulthandler_stack_overflow(PyObject *self)
765{
766 size_t depth, size;
767 void *sp = &depth, *stop;
768
769 depth = 0;
770 stop = stack_overflow(sp - STACK_OVERFLOW_MAX_SIZE,
771 sp + STACK_OVERFLOW_MAX_SIZE,
772 &depth);
773 if (sp < stop)
774 size = stop - sp;
775 else
776 size = sp - stop;
777 PyErr_Format(PyExc_RuntimeError,
778 "unable to raise a stack overflow (allocated %zu bytes "
779 "on the stack, %zu recursive calls)",
780 size, depth);
781 return NULL;
Victor Stinner024e37a2011-03-31 01:31:06 +0200782}
783#endif
784
785
786static int
787faulthandler_traverse(PyObject *module, visitproc visit, void *arg)
788{
789#ifdef FAULTHANDLER_USER
790 unsigned int index;
791#endif
792
793#ifdef FAULTHANDLER_LATER
794 Py_VISIT(thread.file);
795#endif
796#ifdef FAULTHANDLER_USER
797 if (user_signals != NULL) {
798 for (index=0; index < NSIG; index++)
799 Py_VISIT(user_signals[index].file);
800 }
801#endif
802 Py_VISIT(fatal_error.file);
803 return 0;
804}
805
806PyDoc_STRVAR(module_doc,
807"faulthandler module.");
808
809static PyMethodDef module_methods[] = {
810 {"enable",
811 (PyCFunction)faulthandler_enable, METH_VARARGS|METH_KEYWORDS,
812 PyDoc_STR("enable(file=sys.stderr, all_threads=False): "
813 "enable the fault handler")},
814 {"disable", (PyCFunction)faulthandler_disable_py, METH_NOARGS,
815 PyDoc_STR("disable(): disable the fault handler")},
816 {"is_enabled", (PyCFunction)faulthandler_is_enabled, METH_NOARGS,
817 PyDoc_STR("is_enabled()->bool: check if the handler is enabled")},
818 {"dump_traceback",
819 (PyCFunction)faulthandler_dump_traceback_py, METH_VARARGS|METH_KEYWORDS,
820 PyDoc_STR("dump_traceback(file=sys.stderr, all_threads=False): "
821 "dump the traceback of the current thread, or of all threads "
822 "if all_threads is True, into file")},
823#ifdef FAULTHANDLER_LATER
824 {"dump_tracebacks_later",
825 (PyCFunction)faulthandler_dump_traceback_later, METH_VARARGS|METH_KEYWORDS,
826 PyDoc_STR("dump_tracebacks_later(timeout, repeat=False, file=sys.stderr):\n"
827 "dump the traceback of all threads in timeout seconds,\n"
828 "or each timeout seconds if repeat is True.")},
829 {"cancel_dump_tracebacks_later",
Victor Stinner702624e2011-03-31 03:42:34 +0200830 (PyCFunction)faulthandler_cancel_dump_tracebacks_later_py, METH_NOARGS,
Victor Stinner024e37a2011-03-31 01:31:06 +0200831 PyDoc_STR("cancel_dump_tracebacks_later():\ncancel the previous call "
832 "to dump_tracebacks_later().")},
833#endif
834
835#ifdef FAULTHANDLER_USER
836 {"register",
837 (PyCFunction)faulthandler_register, METH_VARARGS|METH_KEYWORDS,
838 PyDoc_STR("register(signum, file=sys.stderr, all_threads=False): "
839 "register an handler for the signal 'signum': dump the "
840 "traceback of the current thread, or of all threads if "
841 "all_threads is True, into file")},
842 {"unregister",
843 faulthandler_unregister_py, METH_VARARGS|METH_KEYWORDS,
844 PyDoc_STR("unregister(signum): unregister the handler of the signal "
845 "'signum' registered by register()")},
846#endif
847
848 {"_read_null", faulthandler_read_null, METH_VARARGS,
849 PyDoc_STR("_read_null(release_gil=False): read from NULL, raise "
850 "a SIGSEGV or SIGBUS signal depending on the platform")},
851 {"_sigsegv", faulthandler_sigsegv, METH_VARARGS,
852 PyDoc_STR("_sigsegv(): raise a SIGSEGV signal")},
853 {"_sigfpe", (PyCFunction)faulthandler_sigfpe, METH_NOARGS,
854 PyDoc_STR("_sigfpe(): raise a SIGFPE signal")},
855#ifdef SIGBUS
856 {"_sigbus", (PyCFunction)faulthandler_sigbus, METH_NOARGS,
857 PyDoc_STR("_sigbus(): raise a SIGBUS signal")},
858#endif
859#ifdef SIGILL
860 {"_sigill", (PyCFunction)faulthandler_sigill, METH_NOARGS,
861 PyDoc_STR("_sigill(): raise a SIGILL signal")},
862#endif
863 {"_fatal_error", faulthandler_fatal_error_py, METH_VARARGS,
864 PyDoc_STR("_fatal_error(message): call Py_FatalError(message)")},
865#if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)
866 {"_stack_overflow", (PyCFunction)faulthandler_stack_overflow, METH_NOARGS,
867 PyDoc_STR("_stack_overflow(): recursive call to raise a stack overflow")},
868#endif
869 {NULL, NULL} /* terminator */
870};
871
872static struct PyModuleDef module_def = {
873 PyModuleDef_HEAD_INIT,
874 "faulthandler",
875 module_doc,
876 0, /* non negative size to be able to unload the module */
877 module_methods,
878 NULL,
879 faulthandler_traverse,
880 NULL,
881 NULL
882};
883
884PyMODINIT_FUNC
885PyInit_faulthandler(void)
886{
887 return PyModule_Create(&module_def);
888}
889
890/* Call faulthandler.enable() if PYTHONFAULTHANDLER environment variable is
891 defined, or if sys._xoptions has a 'faulthandler' key. */
892
893static int
894faulthandler_env_options(void)
895{
896 PyObject *xoptions, *key, *module, *res;
897 int enable;
898
899 if (!Py_GETENV("PYTHONFAULTHANDLER")) {
900 xoptions = PySys_GetXOptions();
901 if (xoptions == NULL)
902 return -1;
903
904 key = PyUnicode_FromString("faulthandler");
905 if (key == NULL)
906 return -1;
907
908 enable = PyDict_Contains(xoptions, key);
909 Py_DECREF(key);
910 if (!enable)
911 return 0;
912 }
913 else
914 enable = 1;
915
916 module = PyImport_ImportModule("faulthandler");
917 if (module == NULL) {
918 return -1;
919 }
920 res = PyObject_CallMethod(module, "enable", "");
921 Py_DECREF(module);
922 if (res == NULL)
923 return -1;
924 Py_DECREF(res);
925 return 0;
926}
927
928int _PyFaulthandler_Init(void)
929{
930#ifdef HAVE_SIGALTSTACK
931 int err;
932
933 /* Try to allocate an alternate stack for faulthandler() signal handler to
934 * be able to allocate memory on the stack, even on a stack overflow. If it
935 * fails, ignore the error. */
936 stack.ss_flags = 0;
937 stack.ss_size = SIGSTKSZ;
938 stack.ss_sp = PyMem_Malloc(stack.ss_size);
939 if (stack.ss_sp != NULL) {
940 err = sigaltstack(&stack, NULL);
941 if (err) {
942 PyMem_Free(stack.ss_sp);
943 stack.ss_sp = NULL;
944 }
945 }
946#endif
947#ifdef FAULTHANDLER_LATER
948 thread.running = 0;
949 thread.file = NULL;
950 thread.cancel_event = PyThread_allocate_lock();
951 thread.join_event = PyThread_allocate_lock();
952 if (!thread.cancel_event || !thread.join_event) {
953 PyErr_SetString(PyExc_RuntimeError,
954 "could not allocate locks for faulthandler");
955 return -1;
956 }
957#endif
958
959 return faulthandler_env_options();
960}
961
962void _PyFaulthandler_Fini(void)
963{
964#ifdef FAULTHANDLER_USER
965 unsigned int i;
966#endif
967
968#ifdef FAULTHANDLER_LATER
969 /* later */
Victor Stinner702624e2011-03-31 03:42:34 +0200970 faulthandler_cancel_dump_tracebacks_later();
Victor Stinner024e37a2011-03-31 01:31:06 +0200971 if (thread.cancel_event) {
972 PyThread_free_lock(thread.cancel_event);
973 thread.cancel_event = NULL;
974 }
975 if (thread.join_event) {
976 PyThread_free_lock(thread.join_event);
977 thread.join_event = NULL;
978 }
979#endif
980
981#ifdef FAULTHANDLER_USER
982 /* user */
983 if (user_signals != NULL) {
984 for (i=0; i < NSIG; i++)
985 faulthandler_unregister(&user_signals[i], i+1);
986 free(user_signals);
987 user_signals = NULL;
988 }
989#endif
990
991 /* fatal */
992 faulthandler_disable();
993#ifdef HAVE_SIGALTSTACK
994 if (stack.ss_sp != NULL) {
995 PyMem_Free(stack.ss_sp);
996 stack.ss_sp = NULL;
997 }
998#endif
999}