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