1 #include "Python.h"
2 #include "pythread.h"
3 #include <signal.h>
4 #include <object.h>
5 #include <frameobject.h>
6 #include <signal.h>
7 #if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK)
8 # include <pthread.h>
9 #endif
10 #ifdef MS_WINDOWS
11 # include <windows.h>
12 #endif
13 #ifdef HAVE_SYS_RESOURCE_H
14 # include <sys/resource.h>
15 #endif
16
17 /* Allocate at maximum 100 MB of the stack to raise the stack overflow */
18 #define STACK_OVERFLOW_MAX_SIZE (100*1024*1024)
19
20 #ifdef WITH_THREAD
21 # define FAULTHANDLER_LATER
22 #endif
23
24 #ifndef MS_WINDOWS
25 /* register() is useless on Windows, because only SIGSEGV, SIGABRT and
26 SIGILL can be handled by the process, and these signals can only be used
27 with enable(), not using register() */
28 # define FAULTHANDLER_USER
29 #endif
30
31 #define PUTS(fd, str) _Py_write_noraise(fd, str, strlen(str))
32
33 _Py_IDENTIFIER(enable);
34 _Py_IDENTIFIER(fileno);
35 _Py_IDENTIFIER(flush);
36 _Py_IDENTIFIER(stderr);
37
38 #ifdef HAVE_SIGACTION
39 typedef struct sigaction _Py_sighandler_t;
40 #else
41 typedef PyOS_sighandler_t _Py_sighandler_t;
42 #endif
43
44 typedef struct {
45 int signum;
46 int enabled;
47 const char* name;
48 _Py_sighandler_t previous;
49 int all_threads;
50 } fault_handler_t;
51
52 static struct {
53 int enabled;
54 PyObject *file;
55 int fd;
56 int all_threads;
57 PyInterpreterState *interp;
58 } fatal_error = {0, NULL, -1, 0};
59
60 #ifdef FAULTHANDLER_LATER
61 static struct {
62 PyObject *file;
63 int fd;
64 PY_TIMEOUT_T timeout_us; /* timeout in microseconds */
65 int repeat;
66 PyInterpreterState *interp;
67 int exit;
68 char *header;
69 size_t header_len;
70 /* The main thread always holds this lock. It is only released when
71 faulthandler_thread() is interrupted before this thread exits, or at
72 Python exit. */
73 PyThread_type_lock cancel_event;
74 /* released by child thread when joined */
75 PyThread_type_lock running;
76 } thread;
77 #endif
78
79 #ifdef FAULTHANDLER_USER
80 typedef struct {
81 int enabled;
82 PyObject *file;
83 int fd;
84 int all_threads;
85 int chain;
86 _Py_sighandler_t previous;
87 PyInterpreterState *interp;
88 } user_signal_t;
89
90 static user_signal_t *user_signals;
91
92 /* the following macros come from Python: Modules/signalmodule.c */
93 #ifndef NSIG
94 # if defined(_NSIG)
95 # define NSIG _NSIG /* For BSD/SysV */
96 # elif defined(_SIGMAX)
97 # define NSIG (_SIGMAX + 1) /* For QNX */
98 # elif defined(SIGMAX)
99 # define NSIG (SIGMAX + 1) /* For djgpp */
100 # else
101 # define NSIG 64 /* Use a reasonable default value */
102 # endif
103 #endif
104
105 static void faulthandler_user(int signum);
106 #endif /* FAULTHANDLER_USER */
107
108
109 static fault_handler_t faulthandler_handlers[] = {
110 #ifdef SIGBUS
111 {SIGBUS, 0, "Bus error", },
112 #endif
113 #ifdef SIGILL
114 {SIGILL, 0, "Illegal instruction", },
115 #endif
116 {SIGFPE, 0, "Floating point exception", },
117 {SIGABRT, 0, "Aborted", },
118 /* define SIGSEGV at the end to make it the default choice if searching the
119 handler fails in faulthandler_fatal_error() */
120 {SIGSEGV, 0, "Segmentation fault", }
121 };
122 static const size_t faulthandler_nsignals = \
123 Py_ARRAY_LENGTH(faulthandler_handlers);
124
125 #ifdef HAVE_SIGALTSTACK
126 static stack_t stack;
127 #endif
128
129
130 /* Get the file descriptor of a file by calling its fileno() method and then
131 call its flush() method.
132
133 If file is NULL or Py_None, use sys.stderr as the new file.
134 If file is an integer, it will be treated as file descriptor.
135
136 On success, return the file descriptor and write the new file into *file_ptr.
137 On error, return -1. */
138
139 static int
faulthandler_get_fileno(PyObject ** file_ptr)140 faulthandler_get_fileno(PyObject **file_ptr)
141 {
142 PyObject *result;
143 long fd_long;
144 int fd;
145 PyObject *file = *file_ptr;
146
147 if (file == NULL || file == Py_None) {
148 file = _PySys_GetObjectId(&PyId_stderr);
149 if (file == NULL) {
150 PyErr_SetString(PyExc_RuntimeError, "unable to get sys.stderr");
151 return -1;
152 }
153 if (file == Py_None) {
154 PyErr_SetString(PyExc_RuntimeError, "sys.stderr is None");
155 return -1;
156 }
157 }
158 else if (PyLong_Check(file)) {
159 fd = _PyLong_AsInt(file);
160 if (fd == -1 && PyErr_Occurred())
161 return -1;
162 if (fd < 0) {
163 PyErr_SetString(PyExc_ValueError,
164 "file is not a valid file descripter");
165 return -1;
166 }
167 *file_ptr = NULL;
168 return fd;
169 }
170
171 result = _PyObject_CallMethodId(file, &PyId_fileno, NULL);
172 if (result == NULL)
173 return -1;
174
175 fd = -1;
176 if (PyLong_Check(result)) {
177 fd_long = PyLong_AsLong(result);
178 if (0 <= fd_long && fd_long < INT_MAX)
179 fd = (int)fd_long;
180 }
181 Py_DECREF(result);
182
183 if (fd == -1) {
184 PyErr_SetString(PyExc_RuntimeError,
185 "file.fileno() is not a valid file descriptor");
186 return -1;
187 }
188
189 result = _PyObject_CallMethodId(file, &PyId_flush, NULL);
190 if (result != NULL)
191 Py_DECREF(result);
192 else {
193 /* ignore flush() error */
194 PyErr_Clear();
195 }
196 *file_ptr = file;
197 return fd;
198 }
199
200 /* Get the state of the current thread: only call this function if the current
201 thread holds the GIL. Raise an exception on error. */
202 static PyThreadState*
get_thread_state(void)203 get_thread_state(void)
204 {
205 PyThreadState *tstate = _PyThreadState_UncheckedGet();
206 if (tstate == NULL) {
207 /* just in case but very unlikely... */
208 PyErr_SetString(PyExc_RuntimeError,
209 "unable to get the current thread state");
210 return NULL;
211 }
212 return tstate;
213 }
214
215 static void
faulthandler_dump_traceback(int fd,int all_threads,PyInterpreterState * interp)216 faulthandler_dump_traceback(int fd, int all_threads,
217 PyInterpreterState *interp)
218 {
219 static volatile int reentrant = 0;
220 PyThreadState *tstate;
221
222 if (reentrant)
223 return;
224
225 reentrant = 1;
226
227 #ifdef WITH_THREAD
228 /* SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals and
229 are thus delivered to the thread that caused the fault. Get the Python
230 thread state of the current thread.
231
232 PyThreadState_Get() doesn't give the state of the thread that caused the
233 fault if the thread released the GIL, and so this function cannot be
234 used. Read the thread local storage (TLS) instead: call
235 PyGILState_GetThisThreadState(). */
236 tstate = PyGILState_GetThisThreadState();
237 #else
238 tstate = _PyThreadState_UncheckedGet();
239 #endif
240
241 if (all_threads) {
242 (void)_Py_DumpTracebackThreads(fd, NULL, tstate);
243 }
244 else {
245 if (tstate != NULL)
246 _Py_DumpTraceback(fd, tstate);
247 }
248
249 reentrant = 0;
250 }
251
252 static PyObject*
faulthandler_dump_traceback_py(PyObject * self,PyObject * args,PyObject * kwargs)253 faulthandler_dump_traceback_py(PyObject *self,
254 PyObject *args, PyObject *kwargs)
255 {
256 static char *kwlist[] = {"file", "all_threads", NULL};
257 PyObject *file = NULL;
258 int all_threads = 1;
259 PyThreadState *tstate;
260 const char *errmsg;
261 int fd;
262
263 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
264 "|Oi:dump_traceback", kwlist,
265 &file, &all_threads))
266 return NULL;
267
268 fd = faulthandler_get_fileno(&file);
269 if (fd < 0)
270 return NULL;
271
272 tstate = get_thread_state();
273 if (tstate == NULL)
274 return NULL;
275
276 if (all_threads) {
277 errmsg = _Py_DumpTracebackThreads(fd, NULL, tstate);
278 if (errmsg != NULL) {
279 PyErr_SetString(PyExc_RuntimeError, errmsg);
280 return NULL;
281 }
282 }
283 else {
284 _Py_DumpTraceback(fd, tstate);
285 }
286
287 if (PyErr_CheckSignals())
288 return NULL;
289
290 Py_RETURN_NONE;
291 }
292
293 static void
faulthandler_disable_fatal_handler(fault_handler_t * handler)294 faulthandler_disable_fatal_handler(fault_handler_t *handler)
295 {
296 if (!handler->enabled)
297 return;
298 handler->enabled = 0;
299 #ifdef HAVE_SIGACTION
300 (void)sigaction(handler->signum, &handler->previous, NULL);
301 #else
302 (void)signal(handler->signum, handler->previous);
303 #endif
304 }
305
306
307 /* Handler for SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL signals.
308
309 Display the current Python traceback, restore the previous handler and call
310 the previous handler.
311
312 On Windows, don't explicitly call the previous handler, because the Windows
313 signal handler would not be called (for an unknown reason). The execution of
314 the program continues at faulthandler_fatal_error() exit, but the same
315 instruction will raise the same fault (signal), and so the previous handler
316 will be called.
317
318 This function is signal-safe and should only call signal-safe functions. */
319
320 static void
faulthandler_fatal_error(int signum)321 faulthandler_fatal_error(int signum)
322 {
323 const int fd = fatal_error.fd;
324 size_t i;
325 fault_handler_t *handler = NULL;
326 int save_errno = errno;
327
328 if (!fatal_error.enabled)
329 return;
330
331 for (i=0; i < faulthandler_nsignals; i++) {
332 handler = &faulthandler_handlers[i];
333 if (handler->signum == signum)
334 break;
335 }
336 if (handler == NULL) {
337 /* faulthandler_nsignals == 0 (unlikely) */
338 return;
339 }
340
341 /* restore the previous handler */
342 faulthandler_disable_fatal_handler(handler);
343
344 PUTS(fd, "Fatal Python error: ");
345 PUTS(fd, handler->name);
346 PUTS(fd, "\n\n");
347
348 faulthandler_dump_traceback(fd, fatal_error.all_threads,
349 fatal_error.interp);
350
351 errno = save_errno;
352 #ifdef MS_WINDOWS
353 if (signum == SIGSEGV) {
354 /* don't explicitly call the previous handler for SIGSEGV in this signal
355 handler, because the Windows signal handler would not be called */
356 return;
357 }
358 #endif
359 /* call the previous signal handler: it is called immediately if we use
360 sigaction() thanks to SA_NODEFER flag, otherwise it is deferred */
361 raise(signum);
362 }
363
364 #ifdef MS_WINDOWS
365 static LONG WINAPI
faulthandler_exc_handler(struct _EXCEPTION_POINTERS * exc_info)366 faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info)
367 {
368 const int fd = fatal_error.fd;
369 DWORD code = exc_info->ExceptionRecord->ExceptionCode;
370 DWORD flags = exc_info->ExceptionRecord->ExceptionFlags;
371
372 /* only log fatal exceptions */
373 if (flags & EXCEPTION_NONCONTINUABLE) {
374 /* call the next exception handler */
375 return EXCEPTION_CONTINUE_SEARCH;
376 }
377
378 PUTS(fd, "Windows fatal exception: ");
379 switch (code)
380 {
381 /* only format most common errors */
382 case EXCEPTION_ACCESS_VIOLATION: PUTS(fd, "access violation"); break;
383 case EXCEPTION_FLT_DIVIDE_BY_ZERO: PUTS(fd, "float divide by zero"); break;
384 case EXCEPTION_FLT_OVERFLOW: PUTS(fd, "float overflow"); break;
385 case EXCEPTION_INT_DIVIDE_BY_ZERO: PUTS(fd, "int divide by zero"); break;
386 case EXCEPTION_INT_OVERFLOW: PUTS(fd, "integer overflow"); break;
387 case EXCEPTION_IN_PAGE_ERROR: PUTS(fd, "page error"); break;
388 case EXCEPTION_STACK_OVERFLOW: PUTS(fd, "stack overflow"); break;
389 default:
390 PUTS(fd, "code ");
391 _Py_DumpDecimal(fd, code);
392 }
393 PUTS(fd, "\n\n");
394
395 if (code == EXCEPTION_ACCESS_VIOLATION) {
396 /* disable signal handler for SIGSEGV */
397 size_t i;
398 for (i=0; i < faulthandler_nsignals; i++) {
399 fault_handler_t *handler = &faulthandler_handlers[i];
400 if (handler->signum == SIGSEGV) {
401 faulthandler_disable_fatal_handler(handler);
402 break;
403 }
404 }
405 }
406
407 faulthandler_dump_traceback(fd, fatal_error.all_threads,
408 fatal_error.interp);
409
410 /* call the next exception handler */
411 return EXCEPTION_CONTINUE_SEARCH;
412 }
413 #endif
414
415 /* Install the handler for fatal signals, faulthandler_fatal_error(). */
416
417 static int
faulthandler_enable(void)418 faulthandler_enable(void)
419 {
420 size_t i;
421
422 if (fatal_error.enabled) {
423 return 0;
424 }
425 fatal_error.enabled = 1;
426
427 for (i=0; i < faulthandler_nsignals; i++) {
428 fault_handler_t *handler;
429 #ifdef HAVE_SIGACTION
430 struct sigaction action;
431 #endif
432 int err;
433
434 handler = &faulthandler_handlers[i];
435 assert(!handler->enabled);
436 #ifdef HAVE_SIGACTION
437 action.sa_handler = faulthandler_fatal_error;
438 sigemptyset(&action.sa_mask);
439 /* Do not prevent the signal from being received from within
440 its own signal handler */
441 action.sa_flags = SA_NODEFER;
442 #ifdef HAVE_SIGALTSTACK
443 if (stack.ss_sp != NULL) {
444 /* Call the signal handler on an alternate signal stack
445 provided by sigaltstack() */
446 action.sa_flags |= SA_ONSTACK;
447 }
448 #endif
449 err = sigaction(handler->signum, &action, &handler->previous);
450 #else
451 handler->previous = signal(handler->signum,
452 faulthandler_fatal_error);
453 err = (handler->previous == SIG_ERR);
454 #endif
455 if (err) {
456 PyErr_SetFromErrno(PyExc_RuntimeError);
457 return -1;
458 }
459
460 handler->enabled = 1;
461 }
462
463 #ifdef MS_WINDOWS
464 AddVectoredExceptionHandler(1, faulthandler_exc_handler);
465 #endif
466 return 0;
467 }
468
469 static PyObject*
faulthandler_py_enable(PyObject * self,PyObject * args,PyObject * kwargs)470 faulthandler_py_enable(PyObject *self, PyObject *args, PyObject *kwargs)
471 {
472 static char *kwlist[] = {"file", "all_threads", NULL};
473 PyObject *file = NULL;
474 int all_threads = 1;
475 int fd;
476 PyThreadState *tstate;
477
478 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
479 "|Oi:enable", kwlist, &file, &all_threads))
480 return NULL;
481
482 fd = faulthandler_get_fileno(&file);
483 if (fd < 0)
484 return NULL;
485
486 tstate = get_thread_state();
487 if (tstate == NULL)
488 return NULL;
489
490 Py_XINCREF(file);
491 Py_XSETREF(fatal_error.file, file);
492 fatal_error.fd = fd;
493 fatal_error.all_threads = all_threads;
494 fatal_error.interp = tstate->interp;
495
496 if (faulthandler_enable() < 0) {
497 return NULL;
498 }
499
500 Py_RETURN_NONE;
501 }
502
503 static void
faulthandler_disable(void)504 faulthandler_disable(void)
505 {
506 unsigned int i;
507 fault_handler_t *handler;
508
509 if (fatal_error.enabled) {
510 fatal_error.enabled = 0;
511 for (i=0; i < faulthandler_nsignals; i++) {
512 handler = &faulthandler_handlers[i];
513 faulthandler_disable_fatal_handler(handler);
514 }
515 }
516
517 Py_CLEAR(fatal_error.file);
518 }
519
520 static PyObject*
faulthandler_disable_py(PyObject * self)521 faulthandler_disable_py(PyObject *self)
522 {
523 if (!fatal_error.enabled) {
524 Py_INCREF(Py_False);
525 return Py_False;
526 }
527 faulthandler_disable();
528 Py_INCREF(Py_True);
529 return Py_True;
530 }
531
532 static PyObject*
faulthandler_is_enabled(PyObject * self)533 faulthandler_is_enabled(PyObject *self)
534 {
535 return PyBool_FromLong(fatal_error.enabled);
536 }
537
538 #ifdef FAULTHANDLER_LATER
539
540 static void
faulthandler_thread(void * unused)541 faulthandler_thread(void *unused)
542 {
543 PyLockStatus st;
544 const char* errmsg;
545 int ok;
546 #if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK)
547 sigset_t set;
548
549 /* we don't want to receive any signal */
550 sigfillset(&set);
551 pthread_sigmask(SIG_SETMASK, &set, NULL);
552 #endif
553
554 do {
555 st = PyThread_acquire_lock_timed(thread.cancel_event,
556 thread.timeout_us, 0);
557 if (st == PY_LOCK_ACQUIRED) {
558 PyThread_release_lock(thread.cancel_event);
559 break;
560 }
561 /* Timeout => dump traceback */
562 assert(st == PY_LOCK_FAILURE);
563
564 _Py_write_noraise(thread.fd, thread.header, (int)thread.header_len);
565
566 errmsg = _Py_DumpTracebackThreads(thread.fd, thread.interp, NULL);
567 ok = (errmsg == NULL);
568
569 if (thread.exit)
570 _exit(1);
571 } while (ok && thread.repeat);
572
573 /* The only way out */
574 PyThread_release_lock(thread.running);
575 }
576
577 static void
cancel_dump_traceback_later(void)578 cancel_dump_traceback_later(void)
579 {
580 /* Notify cancellation */
581 PyThread_release_lock(thread.cancel_event);
582
583 /* Wait for thread to join */
584 PyThread_acquire_lock(thread.running, 1);
585 PyThread_release_lock(thread.running);
586
587 /* The main thread should always hold the cancel_event lock */
588 PyThread_acquire_lock(thread.cancel_event, 1);
589
590 Py_CLEAR(thread.file);
591 if (thread.header) {
592 PyMem_Free(thread.header);
593 thread.header = NULL;
594 }
595 }
596
597 static char*
format_timeout(double timeout)598 format_timeout(double timeout)
599 {
600 unsigned long us, sec, min, hour;
601 double intpart, fracpart;
602 char buffer[100];
603
604 fracpart = modf(timeout, &intpart);
605 sec = (unsigned long)intpart;
606 us = (unsigned long)(fracpart * 1e6);
607 min = sec / 60;
608 sec %= 60;
609 hour = min / 60;
610 min %= 60;
611
612 if (us != 0)
613 PyOS_snprintf(buffer, sizeof(buffer),
614 "Timeout (%lu:%02lu:%02lu.%06lu)!\n",
615 hour, min, sec, us);
616 else
617 PyOS_snprintf(buffer, sizeof(buffer),
618 "Timeout (%lu:%02lu:%02lu)!\n",
619 hour, min, sec);
620
621 return _PyMem_Strdup(buffer);
622 }
623
624 static PyObject*
faulthandler_dump_traceback_later(PyObject * self,PyObject * args,PyObject * kwargs)625 faulthandler_dump_traceback_later(PyObject *self,
626 PyObject *args, PyObject *kwargs)
627 {
628 static char *kwlist[] = {"timeout", "repeat", "file", "exit", NULL};
629 double timeout;
630 PY_TIMEOUT_T timeout_us;
631 int repeat = 0;
632 PyObject *file = NULL;
633 int fd;
634 int exit = 0;
635 PyThreadState *tstate;
636 char *header;
637 size_t header_len;
638
639 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
640 "d|iOi:dump_traceback_later", kwlist,
641 &timeout, &repeat, &file, &exit))
642 return NULL;
643 if ((timeout * 1e6) >= (double) PY_TIMEOUT_MAX) {
644 PyErr_SetString(PyExc_OverflowError, "timeout value is too large");
645 return NULL;
646 }
647 timeout_us = (PY_TIMEOUT_T)(timeout * 1e6);
648 if (timeout_us <= 0) {
649 PyErr_SetString(PyExc_ValueError, "timeout must be greater than 0");
650 return NULL;
651 }
652
653 tstate = get_thread_state();
654 if (tstate == NULL)
655 return NULL;
656
657 fd = faulthandler_get_fileno(&file);
658 if (fd < 0)
659 return NULL;
660
661 /* format the timeout */
662 header = format_timeout(timeout);
663 if (header == NULL)
664 return PyErr_NoMemory();
665 header_len = strlen(header);
666
667 /* Cancel previous thread, if running */
668 cancel_dump_traceback_later();
669
670 Py_XINCREF(file);
671 Py_XSETREF(thread.file, file);
672 thread.fd = fd;
673 thread.timeout_us = timeout_us;
674 thread.repeat = repeat;
675 thread.interp = tstate->interp;
676 thread.exit = exit;
677 thread.header = header;
678 thread.header_len = header_len;
679
680 /* Arm these locks to serve as events when released */
681 PyThread_acquire_lock(thread.running, 1);
682
683 if (PyThread_start_new_thread(faulthandler_thread, NULL) == -1) {
684 PyThread_release_lock(thread.running);
685 Py_CLEAR(thread.file);
686 PyMem_Free(header);
687 thread.header = NULL;
688 PyErr_SetString(PyExc_RuntimeError,
689 "unable to start watchdog thread");
690 return NULL;
691 }
692
693 Py_RETURN_NONE;
694 }
695
696 static PyObject*
faulthandler_cancel_dump_traceback_later_py(PyObject * self)697 faulthandler_cancel_dump_traceback_later_py(PyObject *self)
698 {
699 cancel_dump_traceback_later();
700 Py_RETURN_NONE;
701 }
702 #endif /* FAULTHANDLER_LATER */
703
704 #ifdef FAULTHANDLER_USER
705 static int
faulthandler_register(int signum,int chain,_Py_sighandler_t * p_previous)706 faulthandler_register(int signum, int chain, _Py_sighandler_t *p_previous)
707 {
708 #ifdef HAVE_SIGACTION
709 struct sigaction action;
710 action.sa_handler = faulthandler_user;
711 sigemptyset(&action.sa_mask);
712 /* if the signal is received while the kernel is executing a system
713 call, try to restart the system call instead of interrupting it and
714 return EINTR. */
715 action.sa_flags = SA_RESTART;
716 if (chain) {
717 /* do not prevent the signal from being received from within its
718 own signal handler */
719 action.sa_flags = SA_NODEFER;
720 }
721 #ifdef HAVE_SIGALTSTACK
722 if (stack.ss_sp != NULL) {
723 /* Call the signal handler on an alternate signal stack
724 provided by sigaltstack() */
725 action.sa_flags |= SA_ONSTACK;
726 }
727 #endif
728 return sigaction(signum, &action, p_previous);
729 #else
730 _Py_sighandler_t previous;
731 previous = signal(signum, faulthandler_user);
732 if (p_previous != NULL)
733 *p_previous = previous;
734 return (previous == SIG_ERR);
735 #endif
736 }
737
738 /* Handler of user signals (e.g. SIGUSR1).
739
740 Dump the traceback of the current thread, or of all threads if
741 thread.all_threads is true.
742
743 This function is signal safe and should only call signal safe functions. */
744
745 static void
faulthandler_user(int signum)746 faulthandler_user(int signum)
747 {
748 user_signal_t *user;
749 int save_errno = errno;
750
751 user = &user_signals[signum];
752 if (!user->enabled)
753 return;
754
755 faulthandler_dump_traceback(user->fd, user->all_threads, user->interp);
756
757 #ifdef HAVE_SIGACTION
758 if (user->chain) {
759 (void)sigaction(signum, &user->previous, NULL);
760 errno = save_errno;
761
762 /* call the previous signal handler */
763 raise(signum);
764
765 save_errno = errno;
766 (void)faulthandler_register(signum, user->chain, NULL);
767 errno = save_errno;
768 }
769 #else
770 if (user->chain) {
771 errno = save_errno;
772 /* call the previous signal handler */
773 user->previous(signum);
774 }
775 #endif
776 }
777
778 static int
check_signum(int signum)779 check_signum(int signum)
780 {
781 unsigned int i;
782
783 for (i=0; i < faulthandler_nsignals; i++) {
784 if (faulthandler_handlers[i].signum == signum) {
785 PyErr_Format(PyExc_RuntimeError,
786 "signal %i cannot be registered, "
787 "use enable() instead",
788 signum);
789 return 0;
790 }
791 }
792 if (signum < 1 || NSIG <= signum) {
793 PyErr_SetString(PyExc_ValueError, "signal number out of range");
794 return 0;
795 }
796 return 1;
797 }
798
799 static PyObject*
faulthandler_register_py(PyObject * self,PyObject * args,PyObject * kwargs)800 faulthandler_register_py(PyObject *self,
801 PyObject *args, PyObject *kwargs)
802 {
803 static char *kwlist[] = {"signum", "file", "all_threads", "chain", NULL};
804 int signum;
805 PyObject *file = NULL;
806 int all_threads = 1;
807 int chain = 0;
808 int fd;
809 user_signal_t *user;
810 _Py_sighandler_t previous;
811 PyThreadState *tstate;
812 int err;
813
814 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
815 "i|Oii:register", kwlist,
816 &signum, &file, &all_threads, &chain))
817 return NULL;
818
819 if (!check_signum(signum))
820 return NULL;
821
822 tstate = get_thread_state();
823 if (tstate == NULL)
824 return NULL;
825
826 fd = faulthandler_get_fileno(&file);
827 if (fd < 0)
828 return NULL;
829
830 if (user_signals == NULL) {
831 user_signals = PyMem_Malloc(NSIG * sizeof(user_signal_t));
832 if (user_signals == NULL)
833 return PyErr_NoMemory();
834 memset(user_signals, 0, NSIG * sizeof(user_signal_t));
835 }
836 user = &user_signals[signum];
837
838 if (!user->enabled) {
839 err = faulthandler_register(signum, chain, &previous);
840 if (err) {
841 PyErr_SetFromErrno(PyExc_OSError);
842 return NULL;
843 }
844
845 user->previous = previous;
846 }
847
848 Py_XINCREF(file);
849 Py_XSETREF(user->file, file);
850 user->fd = fd;
851 user->all_threads = all_threads;
852 user->chain = chain;
853 user->interp = tstate->interp;
854 user->enabled = 1;
855
856 Py_RETURN_NONE;
857 }
858
859 static int
faulthandler_unregister(user_signal_t * user,int signum)860 faulthandler_unregister(user_signal_t *user, int signum)
861 {
862 if (!user->enabled)
863 return 0;
864 user->enabled = 0;
865 #ifdef HAVE_SIGACTION
866 (void)sigaction(signum, &user->previous, NULL);
867 #else
868 (void)signal(signum, user->previous);
869 #endif
870 Py_CLEAR(user->file);
871 user->fd = -1;
872 return 1;
873 }
874
875 static PyObject*
faulthandler_unregister_py(PyObject * self,PyObject * args)876 faulthandler_unregister_py(PyObject *self, PyObject *args)
877 {
878 int signum;
879 user_signal_t *user;
880 int change;
881
882 if (!PyArg_ParseTuple(args, "i:unregister", &signum))
883 return NULL;
884
885 if (!check_signum(signum))
886 return NULL;
887
888 if (user_signals == NULL)
889 Py_RETURN_FALSE;
890
891 user = &user_signals[signum];
892 change = faulthandler_unregister(user, signum);
893 return PyBool_FromLong(change);
894 }
895 #endif /* FAULTHANDLER_USER */
896
897
898 static void
faulthandler_suppress_crash_report(void)899 faulthandler_suppress_crash_report(void)
900 {
901 #ifdef MS_WINDOWS
902 UINT mode;
903
904 /* Configure Windows to not display the Windows Error Reporting dialog */
905 mode = SetErrorMode(SEM_NOGPFAULTERRORBOX);
906 SetErrorMode(mode | SEM_NOGPFAULTERRORBOX);
907 #endif
908
909 #ifdef HAVE_SYS_RESOURCE_H
910 struct rlimit rl;
911
912 /* Disable creation of core dump */
913 if (getrlimit(RLIMIT_CORE, &rl) != 0) {
914 rl.rlim_cur = 0;
915 setrlimit(RLIMIT_CORE, &rl);
916 }
917 #endif
918
919 #ifdef _MSC_VER
920 /* Visual Studio: configure abort() to not display an error message nor
921 open a popup asking to report the fault. */
922 _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
923 #endif
924 }
925
926 static PyObject *
faulthandler_read_null(PyObject * self,PyObject * args)927 faulthandler_read_null(PyObject *self, PyObject *args)
928 {
929 volatile int *x;
930 volatile int y;
931
932 faulthandler_suppress_crash_report();
933 x = NULL;
934 y = *x;
935 return PyLong_FromLong(y);
936
937 }
938
939 static void
faulthandler_raise_sigsegv(void)940 faulthandler_raise_sigsegv(void)
941 {
942 faulthandler_suppress_crash_report();
943 #if defined(MS_WINDOWS)
944 /* For SIGSEGV, faulthandler_fatal_error() restores the previous signal
945 handler and then gives back the execution flow to the program (without
946 explicitly calling the previous error handler). In a normal case, the
947 SIGSEGV was raised by the kernel because of a fault, and so if the
948 program retries to execute the same instruction, the fault will be
949 raised again.
950
951 Here the fault is simulated by a fake SIGSEGV signal raised by the
952 application. We have to raise SIGSEGV at lease twice: once for
953 faulthandler_fatal_error(), and one more time for the previous signal
954 handler. */
955 while(1)
956 raise(SIGSEGV);
957 #else
958 raise(SIGSEGV);
959 #endif
960 }
961
962 static PyObject *
faulthandler_sigsegv(PyObject * self,PyObject * args)963 faulthandler_sigsegv(PyObject *self, PyObject *args)
964 {
965 int release_gil = 0;
966 if (!PyArg_ParseTuple(args, "|i:_sigsegv", &release_gil))
967 return NULL;
968
969 if (release_gil) {
970 Py_BEGIN_ALLOW_THREADS
971 faulthandler_raise_sigsegv();
972 Py_END_ALLOW_THREADS
973 } else {
974 faulthandler_raise_sigsegv();
975 }
976 Py_RETURN_NONE;
977 }
978
979 #ifdef WITH_THREAD
980 static void
faulthandler_fatal_error_thread(void * plock)981 faulthandler_fatal_error_thread(void *plock)
982 {
983 PyThread_type_lock *lock = (PyThread_type_lock *)plock;
984
985 Py_FatalError("in new thread");
986
987 /* notify the caller that we are done */
988 PyThread_release_lock(lock);
989 }
990
991 static PyObject *
faulthandler_fatal_error_c_thread(PyObject * self,PyObject * args)992 faulthandler_fatal_error_c_thread(PyObject *self, PyObject *args)
993 {
994 long thread;
995 PyThread_type_lock lock;
996
997 faulthandler_suppress_crash_report();
998
999 lock = PyThread_allocate_lock();
1000 if (lock == NULL)
1001 return PyErr_NoMemory();
1002
1003 PyThread_acquire_lock(lock, WAIT_LOCK);
1004
1005 thread = PyThread_start_new_thread(faulthandler_fatal_error_thread, lock);
1006 if (thread == -1) {
1007 PyThread_free_lock(lock);
1008 PyErr_SetString(PyExc_RuntimeError, "unable to start the thread");
1009 return NULL;
1010 }
1011
1012 /* wait until the thread completes: it will never occur, since Py_FatalError()
1013 exits the process immedialty. */
1014 PyThread_acquire_lock(lock, WAIT_LOCK);
1015 PyThread_release_lock(lock);
1016 PyThread_free_lock(lock);
1017
1018 Py_RETURN_NONE;
1019 }
1020 #endif
1021
1022 static PyObject *
faulthandler_sigfpe(PyObject * self,PyObject * args)1023 faulthandler_sigfpe(PyObject *self, PyObject *args)
1024 {
1025 /* Do an integer division by zero: raise a SIGFPE on Intel CPU, but not on
1026 PowerPC. Use volatile to disable compile-time optimizations. */
1027 volatile int x = 1, y = 0, z;
1028 faulthandler_suppress_crash_report();
1029 z = x / y;
1030 /* If the division by zero didn't raise a SIGFPE (e.g. on PowerPC),
1031 raise it manually. */
1032 raise(SIGFPE);
1033 /* This line is never reached, but we pretend to make something with z
1034 to silence a compiler warning. */
1035 return PyLong_FromLong(z);
1036 }
1037
1038 static PyObject *
faulthandler_sigabrt(PyObject * self,PyObject * args)1039 faulthandler_sigabrt(PyObject *self, PyObject *args)
1040 {
1041 faulthandler_suppress_crash_report();
1042 abort();
1043 Py_RETURN_NONE;
1044 }
1045
1046 static PyObject *
faulthandler_fatal_error_py(PyObject * self,PyObject * args)1047 faulthandler_fatal_error_py(PyObject *self, PyObject *args)
1048 {
1049 char *message;
1050 int release_gil = 0;
1051 if (!PyArg_ParseTuple(args, "y|i:fatal_error", &message, &release_gil))
1052 return NULL;
1053 faulthandler_suppress_crash_report();
1054 if (release_gil) {
1055 Py_BEGIN_ALLOW_THREADS
1056 Py_FatalError(message);
1057 Py_END_ALLOW_THREADS
1058 }
1059 else {
1060 Py_FatalError(message);
1061 }
1062 Py_RETURN_NONE;
1063 }
1064
1065 #if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)
1066 #define FAULTHANDLER_STACK_OVERFLOW
1067
1068 #ifdef __INTEL_COMPILER
1069 /* Issue #23654: Turn off ICC's tail call optimization for the
1070 * stack_overflow generator. ICC turns the recursive tail call into
1071 * a loop. */
1072 # pragma intel optimization_level 0
1073 #endif
1074 static
1075 uintptr_t
stack_overflow(uintptr_t min_sp,uintptr_t max_sp,size_t * depth)1076 stack_overflow(uintptr_t min_sp, uintptr_t max_sp, size_t *depth)
1077 {
1078 /* allocate 4096 bytes on the stack at each call */
1079 unsigned char buffer[4096];
1080 uintptr_t sp = (uintptr_t)&buffer;
1081 *depth += 1;
1082 if (sp < min_sp || max_sp < sp)
1083 return sp;
1084 buffer[0] = 1;
1085 buffer[4095] = 0;
1086 return stack_overflow(min_sp, max_sp, depth);
1087 }
1088
1089 static PyObject *
faulthandler_stack_overflow(PyObject * self)1090 faulthandler_stack_overflow(PyObject *self)
1091 {
1092 size_t depth, size;
1093 uintptr_t sp = (uintptr_t)&depth;
1094 uintptr_t stop;
1095
1096 faulthandler_suppress_crash_report();
1097 depth = 0;
1098 stop = stack_overflow(sp - STACK_OVERFLOW_MAX_SIZE,
1099 sp + STACK_OVERFLOW_MAX_SIZE,
1100 &depth);
1101 if (sp < stop)
1102 size = stop - sp;
1103 else
1104 size = sp - stop;
1105 PyErr_Format(PyExc_RuntimeError,
1106 "unable to raise a stack overflow (allocated %zu bytes "
1107 "on the stack, %zu recursive calls)",
1108 size, depth);
1109 return NULL;
1110 }
1111 #endif /* defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION) */
1112
1113
1114 static int
faulthandler_traverse(PyObject * module,visitproc visit,void * arg)1115 faulthandler_traverse(PyObject *module, visitproc visit, void *arg)
1116 {
1117 #ifdef FAULTHANDLER_USER
1118 unsigned int signum;
1119 #endif
1120
1121 #ifdef FAULTHANDLER_LATER
1122 Py_VISIT(thread.file);
1123 #endif
1124 #ifdef FAULTHANDLER_USER
1125 if (user_signals != NULL) {
1126 for (signum=0; signum < NSIG; signum++)
1127 Py_VISIT(user_signals[signum].file);
1128 }
1129 #endif
1130 Py_VISIT(fatal_error.file);
1131 return 0;
1132 }
1133
1134 #ifdef MS_WINDOWS
1135 static PyObject *
faulthandler_raise_exception(PyObject * self,PyObject * args)1136 faulthandler_raise_exception(PyObject *self, PyObject *args)
1137 {
1138 unsigned int code, flags = 0;
1139 if (!PyArg_ParseTuple(args, "I|I:_raise_exception", &code, &flags))
1140 return NULL;
1141 faulthandler_suppress_crash_report();
1142 RaiseException(code, flags, 0, NULL);
1143 Py_RETURN_NONE;
1144 }
1145 #endif
1146
1147 PyDoc_STRVAR(module_doc,
1148 "faulthandler module.");
1149
1150 static PyMethodDef module_methods[] = {
1151 {"enable",
1152 (PyCFunction)faulthandler_py_enable, METH_VARARGS|METH_KEYWORDS,
1153 PyDoc_STR("enable(file=sys.stderr, all_threads=True): "
1154 "enable the fault handler")},
1155 {"disable", (PyCFunction)faulthandler_disable_py, METH_NOARGS,
1156 PyDoc_STR("disable(): disable the fault handler")},
1157 {"is_enabled", (PyCFunction)faulthandler_is_enabled, METH_NOARGS,
1158 PyDoc_STR("is_enabled()->bool: check if the handler is enabled")},
1159 {"dump_traceback",
1160 (PyCFunction)faulthandler_dump_traceback_py, METH_VARARGS|METH_KEYWORDS,
1161 PyDoc_STR("dump_traceback(file=sys.stderr, all_threads=True): "
1162 "dump the traceback of the current thread, or of all threads "
1163 "if all_threads is True, into file")},
1164 #ifdef FAULTHANDLER_LATER
1165 {"dump_traceback_later",
1166 (PyCFunction)faulthandler_dump_traceback_later, METH_VARARGS|METH_KEYWORDS,
1167 PyDoc_STR("dump_traceback_later(timeout, repeat=False, file=sys.stderrn, exit=False):\n"
1168 "dump the traceback of all threads in timeout seconds,\n"
1169 "or each timeout seconds if repeat is True. If exit is True, "
1170 "call _exit(1) which is not safe.")},
1171 {"cancel_dump_traceback_later",
1172 (PyCFunction)faulthandler_cancel_dump_traceback_later_py, METH_NOARGS,
1173 PyDoc_STR("cancel_dump_traceback_later():\ncancel the previous call "
1174 "to dump_traceback_later().")},
1175 #endif
1176
1177 #ifdef FAULTHANDLER_USER
1178 {"register",
1179 (PyCFunction)faulthandler_register_py, METH_VARARGS|METH_KEYWORDS,
1180 PyDoc_STR("register(signum, file=sys.stderr, all_threads=True, chain=False): "
1181 "register a handler for the signal 'signum': dump the "
1182 "traceback of the current thread, or of all threads if "
1183 "all_threads is True, into file")},
1184 {"unregister",
1185 faulthandler_unregister_py, METH_VARARGS|METH_KEYWORDS,
1186 PyDoc_STR("unregister(signum): unregister the handler of the signal "
1187 "'signum' registered by register()")},
1188 #endif
1189
1190 {"_read_null", faulthandler_read_null, METH_NOARGS,
1191 PyDoc_STR("_read_null(): read from NULL, raise "
1192 "a SIGSEGV or SIGBUS signal depending on the platform")},
1193 {"_sigsegv", faulthandler_sigsegv, METH_VARARGS,
1194 PyDoc_STR("_sigsegv(release_gil=False): raise a SIGSEGV signal")},
1195 #ifdef WITH_THREAD
1196 {"_fatal_error_c_thread", faulthandler_fatal_error_c_thread, METH_NOARGS,
1197 PyDoc_STR("fatal_error_c_thread(): "
1198 "call Py_FatalError() in a new C thread.")},
1199 #endif
1200 {"_sigabrt", faulthandler_sigabrt, METH_NOARGS,
1201 PyDoc_STR("_sigabrt(): raise a SIGABRT signal")},
1202 {"_sigfpe", (PyCFunction)faulthandler_sigfpe, METH_NOARGS,
1203 PyDoc_STR("_sigfpe(): raise a SIGFPE signal")},
1204 {"_fatal_error", faulthandler_fatal_error_py, METH_VARARGS,
1205 PyDoc_STR("_fatal_error(message): call Py_FatalError(message)")},
1206 #ifdef FAULTHANDLER_STACK_OVERFLOW
1207 {"_stack_overflow", (PyCFunction)faulthandler_stack_overflow, METH_NOARGS,
1208 PyDoc_STR("_stack_overflow(): recursive call to raise a stack overflow")},
1209 #endif
1210 #ifdef MS_WINDOWS
1211 {"_raise_exception", faulthandler_raise_exception, METH_VARARGS,
1212 PyDoc_STR("raise_exception(code, flags=0): Call RaiseException(code, flags).")},
1213 #endif
1214 {NULL, NULL} /* sentinel */
1215 };
1216
1217 static struct PyModuleDef module_def = {
1218 PyModuleDef_HEAD_INIT,
1219 "faulthandler",
1220 module_doc,
1221 0, /* non-negative size to be able to unload the module */
1222 module_methods,
1223 NULL,
1224 faulthandler_traverse,
1225 NULL,
1226 NULL
1227 };
1228
1229 PyMODINIT_FUNC
PyInit_faulthandler(void)1230 PyInit_faulthandler(void)
1231 {
1232 PyObject *m = PyModule_Create(&module_def);
1233 if (m == NULL)
1234 return NULL;
1235
1236 /* Add constants for unit tests */
1237 #ifdef MS_WINDOWS
1238 /* RaiseException() codes (prefixed by an underscore) */
1239 if (PyModule_AddIntConstant(m, "_EXCEPTION_ACCESS_VIOLATION",
1240 EXCEPTION_ACCESS_VIOLATION))
1241 return NULL;
1242 if (PyModule_AddIntConstant(m, "_EXCEPTION_INT_DIVIDE_BY_ZERO",
1243 EXCEPTION_INT_DIVIDE_BY_ZERO))
1244 return NULL;
1245 if (PyModule_AddIntConstant(m, "_EXCEPTION_STACK_OVERFLOW",
1246 EXCEPTION_STACK_OVERFLOW))
1247 return NULL;
1248
1249 /* RaiseException() flags (prefixed by an underscore) */
1250 if (PyModule_AddIntConstant(m, "_EXCEPTION_NONCONTINUABLE",
1251 EXCEPTION_NONCONTINUABLE))
1252 return NULL;
1253 if (PyModule_AddIntConstant(m, "_EXCEPTION_NONCONTINUABLE_EXCEPTION",
1254 EXCEPTION_NONCONTINUABLE_EXCEPTION))
1255 return NULL;
1256 #endif
1257
1258 return m;
1259 }
1260
1261 /* Call faulthandler.enable() if the PYTHONFAULTHANDLER environment variable
1262 is defined, or if sys._xoptions has a 'faulthandler' key. */
1263
1264 static int
faulthandler_env_options(void)1265 faulthandler_env_options(void)
1266 {
1267 PyObject *xoptions, *key, *module, *res;
1268 char *p;
1269
1270 if (!((p = Py_GETENV("PYTHONFAULTHANDLER")) && *p != '\0')) {
1271 /* PYTHONFAULTHANDLER environment variable is missing
1272 or an empty string */
1273 int has_key;
1274
1275 xoptions = PySys_GetXOptions();
1276 if (xoptions == NULL)
1277 return -1;
1278
1279 key = PyUnicode_FromString("faulthandler");
1280 if (key == NULL)
1281 return -1;
1282
1283 has_key = PyDict_Contains(xoptions, key);
1284 Py_DECREF(key);
1285 if (has_key <= 0)
1286 return has_key;
1287 }
1288
1289 module = PyImport_ImportModule("faulthandler");
1290 if (module == NULL) {
1291 return -1;
1292 }
1293 res = _PyObject_CallMethodId(module, &PyId_enable, NULL);
1294 Py_DECREF(module);
1295 if (res == NULL)
1296 return -1;
1297 Py_DECREF(res);
1298 return 0;
1299 }
1300
_PyFaulthandler_Init(void)1301 int _PyFaulthandler_Init(void)
1302 {
1303 #ifdef HAVE_SIGALTSTACK
1304 int err;
1305
1306 /* Try to allocate an alternate stack for faulthandler() signal handler to
1307 * be able to allocate memory on the stack, even on a stack overflow. If it
1308 * fails, ignore the error. */
1309 stack.ss_flags = 0;
1310 stack.ss_size = SIGSTKSZ;
1311 stack.ss_sp = PyMem_Malloc(stack.ss_size);
1312 if (stack.ss_sp != NULL) {
1313 err = sigaltstack(&stack, NULL);
1314 if (err) {
1315 PyMem_Free(stack.ss_sp);
1316 stack.ss_sp = NULL;
1317 }
1318 }
1319 #endif
1320 #ifdef FAULTHANDLER_LATER
1321 thread.file = NULL;
1322 thread.cancel_event = PyThread_allocate_lock();
1323 thread.running = PyThread_allocate_lock();
1324 if (!thread.cancel_event || !thread.running) {
1325 PyErr_SetString(PyExc_RuntimeError,
1326 "could not allocate locks for faulthandler");
1327 return -1;
1328 }
1329 PyThread_acquire_lock(thread.cancel_event, 1);
1330 #endif
1331
1332 return faulthandler_env_options();
1333 }
1334
_PyFaulthandler_Fini(void)1335 void _PyFaulthandler_Fini(void)
1336 {
1337 #ifdef FAULTHANDLER_USER
1338 unsigned int signum;
1339 #endif
1340
1341 #ifdef FAULTHANDLER_LATER
1342 /* later */
1343 if (thread.cancel_event) {
1344 cancel_dump_traceback_later();
1345 PyThread_release_lock(thread.cancel_event);
1346 PyThread_free_lock(thread.cancel_event);
1347 thread.cancel_event = NULL;
1348 }
1349 if (thread.running) {
1350 PyThread_free_lock(thread.running);
1351 thread.running = NULL;
1352 }
1353 #endif
1354
1355 #ifdef FAULTHANDLER_USER
1356 /* user */
1357 if (user_signals != NULL) {
1358 for (signum=0; signum < NSIG; signum++)
1359 faulthandler_unregister(&user_signals[signum], signum);
1360 PyMem_Free(user_signals);
1361 user_signals = NULL;
1362 }
1363 #endif
1364
1365 /* fatal */
1366 faulthandler_disable();
1367 #ifdef HAVE_SIGALTSTACK
1368 if (stack.ss_sp != NULL) {
1369 PyMem_Free(stack.ss_sp);
1370 stack.ss_sp = NULL;
1371 }
1372 #endif
1373 }
1374