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