Home | History | Annotate | Download | only in Modules
      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
    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*
    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
    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*
    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
    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
    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
    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
    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*
    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
    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*
    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*
    533 faulthandler_is_enabled(PyObject *self)
    534 {
    535     return PyBool_FromLong(fatal_error.enabled);
    536 }
    537 
    538 #ifdef FAULTHANDLER_LATER
    539 
    540 static void
    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
    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*
    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*
    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*
    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
    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
    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
    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*
    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
    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*
    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
    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 *
    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
    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 *
    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
    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 *
    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 *
   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 *
   1039 faulthandler_sigabrt(PyObject *self, PyObject *args)
   1040 {
   1041     faulthandler_suppress_crash_report();
   1042     abort();
   1043     Py_RETURN_NONE;
   1044 }
   1045 
   1046 static PyObject *
   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
   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 *
   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
   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 *
   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
   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
   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 
   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 
   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