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 39typedef struct sigaction _Py_sighandler_t; 40#else 41typedef PyOS_sighandler_t _Py_sighandler_t; 42#endif 43 44typedef 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 52static 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 61static 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 80typedef 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 90static 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 105static void faulthandler_user(int signum); 106#endif /* FAULTHANDLER_USER */ 107 108 109static 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}; 122static const size_t faulthandler_nsignals = \ 123 Py_ARRAY_LENGTH(faulthandler_handlers); 124 125#ifdef HAVE_SIGALTSTACK 126static 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 139static int 140faulthandler_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. */ 202static PyThreadState* 203get_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 215static void 216faulthandler_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 252static PyObject* 253faulthandler_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 293static void 294faulthandler_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 320static void 321faulthandler_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 365static LONG WINAPI 366faulthandler_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 417static int 418faulthandler_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 469static PyObject* 470faulthandler_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 503static void 504faulthandler_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 520static PyObject* 521faulthandler_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 532static PyObject* 533faulthandler_is_enabled(PyObject *self) 534{ 535 return PyBool_FromLong(fatal_error.enabled); 536} 537 538#ifdef FAULTHANDLER_LATER 539 540static void 541faulthandler_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 577static void 578cancel_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 597static char* 598format_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 624static PyObject* 625faulthandler_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 696static PyObject* 697faulthandler_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 705static int 706faulthandler_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 745static void 746faulthandler_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 778static int 779check_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 799static PyObject* 800faulthandler_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 859static int 860faulthandler_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 875static PyObject* 876faulthandler_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 898static void 899faulthandler_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 926static PyObject * 927faulthandler_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 939static void 940faulthandler_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 962static PyObject * 963faulthandler_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 980static void 981faulthandler_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 991static PyObject * 992faulthandler_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 1022static PyObject * 1023faulthandler_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 1038static PyObject * 1039faulthandler_sigabrt(PyObject *self, PyObject *args) 1040{ 1041 faulthandler_suppress_crash_report(); 1042 abort(); 1043 Py_RETURN_NONE; 1044} 1045 1046static PyObject * 1047faulthandler_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 1074static 1075uintptr_t 1076stack_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 1089static PyObject * 1090faulthandler_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 1114static int 1115faulthandler_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 1135static PyObject * 1136faulthandler_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 1147PyDoc_STRVAR(module_doc, 1148"faulthandler module."); 1149 1150static 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 1217static 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 1229PyMODINIT_FUNC 1230PyInit_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 1264static int 1265faulthandler_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 1301int _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 1335void _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