xref: /third_party/python/Modules/faulthandler.c (revision 7db96d56)
17db96d56Sopenharmony_ci#include "Python.h"
27db96d56Sopenharmony_ci#include "pycore_initconfig.h"    // _PyStatus_ERR
37db96d56Sopenharmony_ci#include "pycore_pyerrors.h"      // _Py_DumpExtensionModules
47db96d56Sopenharmony_ci#include "pycore_pystate.h"       // _PyThreadState_GET()
57db96d56Sopenharmony_ci#include "pycore_signal.h"        // Py_NSIG
67db96d56Sopenharmony_ci#include "pycore_traceback.h"     // _Py_DumpTracebackThreads
77db96d56Sopenharmony_ci
87db96d56Sopenharmony_ci#include <object.h>
97db96d56Sopenharmony_ci#include <signal.h>
107db96d56Sopenharmony_ci#include <signal.h>
117db96d56Sopenharmony_ci#include <stdlib.h>               // abort()
127db96d56Sopenharmony_ci#if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK) && defined(HAVE_PTHREAD_H)
137db96d56Sopenharmony_ci#  include <pthread.h>
147db96d56Sopenharmony_ci#endif
157db96d56Sopenharmony_ci#ifdef MS_WINDOWS
167db96d56Sopenharmony_ci#  include <windows.h>
177db96d56Sopenharmony_ci#endif
187db96d56Sopenharmony_ci#ifdef HAVE_SYS_RESOURCE_H
197db96d56Sopenharmony_ci#  include <sys/resource.h>
207db96d56Sopenharmony_ci#endif
217db96d56Sopenharmony_ci
227db96d56Sopenharmony_ci/* Using an alternative stack requires sigaltstack()
237db96d56Sopenharmony_ci   and sigaction() SA_ONSTACK */
247db96d56Sopenharmony_ci#if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)
257db96d56Sopenharmony_ci#  define FAULTHANDLER_USE_ALT_STACK
267db96d56Sopenharmony_ci#endif
277db96d56Sopenharmony_ci
287db96d56Sopenharmony_ci#if defined(FAULTHANDLER_USE_ALT_STACK) && defined(HAVE_LINUX_AUXVEC_H) && defined(HAVE_SYS_AUXV_H)
297db96d56Sopenharmony_ci#  include <linux/auxvec.h>       // AT_MINSIGSTKSZ
307db96d56Sopenharmony_ci#  include <sys/auxv.h>           // getauxval()
317db96d56Sopenharmony_ci#endif
327db96d56Sopenharmony_ci
337db96d56Sopenharmony_ci/* Allocate at maximum 100 MiB of the stack to raise the stack overflow */
347db96d56Sopenharmony_ci#define STACK_OVERFLOW_MAX_SIZE (100 * 1024 * 1024)
357db96d56Sopenharmony_ci
367db96d56Sopenharmony_ci#ifndef MS_WINDOWS
377db96d56Sopenharmony_ci   /* register() is useless on Windows, because only SIGSEGV, SIGABRT and
387db96d56Sopenharmony_ci      SIGILL can be handled by the process, and these signals can only be used
397db96d56Sopenharmony_ci      with enable(), not using register() */
407db96d56Sopenharmony_ci#  define FAULTHANDLER_USER
417db96d56Sopenharmony_ci#endif
427db96d56Sopenharmony_ci
437db96d56Sopenharmony_ci#define PUTS(fd, str) _Py_write_noraise(fd, str, strlen(str))
447db96d56Sopenharmony_ci
457db96d56Sopenharmony_ci
467db96d56Sopenharmony_ci// clang uses __attribute__((no_sanitize("undefined")))
477db96d56Sopenharmony_ci// GCC 4.9+ uses __attribute__((no_sanitize_undefined))
487db96d56Sopenharmony_ci#if defined(__has_feature)  // Clang
497db96d56Sopenharmony_ci#  if __has_feature(undefined_behavior_sanitizer)
507db96d56Sopenharmony_ci#    define _Py_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined")))
517db96d56Sopenharmony_ci#  endif
527db96d56Sopenharmony_ci#endif
537db96d56Sopenharmony_ci#if defined(__GNUC__) \
547db96d56Sopenharmony_ci    && ((__GNUC__ >= 5) || (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9))
557db96d56Sopenharmony_ci#  define _Py_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined))
567db96d56Sopenharmony_ci#endif
577db96d56Sopenharmony_ci#ifndef _Py_NO_SANITIZE_UNDEFINED
587db96d56Sopenharmony_ci#  define _Py_NO_SANITIZE_UNDEFINED
597db96d56Sopenharmony_ci#endif
607db96d56Sopenharmony_ci
617db96d56Sopenharmony_ci
627db96d56Sopenharmony_ci#ifdef HAVE_SIGACTION
637db96d56Sopenharmony_citypedef struct sigaction _Py_sighandler_t;
647db96d56Sopenharmony_ci#else
657db96d56Sopenharmony_citypedef PyOS_sighandler_t _Py_sighandler_t;
667db96d56Sopenharmony_ci#endif
677db96d56Sopenharmony_ci
687db96d56Sopenharmony_citypedef struct {
697db96d56Sopenharmony_ci    int signum;
707db96d56Sopenharmony_ci    int enabled;
717db96d56Sopenharmony_ci    const char* name;
727db96d56Sopenharmony_ci    _Py_sighandler_t previous;
737db96d56Sopenharmony_ci    int all_threads;
747db96d56Sopenharmony_ci} fault_handler_t;
757db96d56Sopenharmony_ci
767db96d56Sopenharmony_cistatic struct {
777db96d56Sopenharmony_ci    int enabled;
787db96d56Sopenharmony_ci    PyObject *file;
797db96d56Sopenharmony_ci    int fd;
807db96d56Sopenharmony_ci    int all_threads;
817db96d56Sopenharmony_ci    PyInterpreterState *interp;
827db96d56Sopenharmony_ci#ifdef MS_WINDOWS
837db96d56Sopenharmony_ci    void *exc_handler;
847db96d56Sopenharmony_ci#endif
857db96d56Sopenharmony_ci} fatal_error = {0, NULL, -1, 0};
867db96d56Sopenharmony_ci
877db96d56Sopenharmony_cistatic struct {
887db96d56Sopenharmony_ci    PyObject *file;
897db96d56Sopenharmony_ci    int fd;
907db96d56Sopenharmony_ci    PY_TIMEOUT_T timeout_us;   /* timeout in microseconds */
917db96d56Sopenharmony_ci    int repeat;
927db96d56Sopenharmony_ci    PyInterpreterState *interp;
937db96d56Sopenharmony_ci    int exit;
947db96d56Sopenharmony_ci    char *header;
957db96d56Sopenharmony_ci    size_t header_len;
967db96d56Sopenharmony_ci    /* The main thread always holds this lock. It is only released when
977db96d56Sopenharmony_ci       faulthandler_thread() is interrupted before this thread exits, or at
987db96d56Sopenharmony_ci       Python exit. */
997db96d56Sopenharmony_ci    PyThread_type_lock cancel_event;
1007db96d56Sopenharmony_ci    /* released by child thread when joined */
1017db96d56Sopenharmony_ci    PyThread_type_lock running;
1027db96d56Sopenharmony_ci} thread;
1037db96d56Sopenharmony_ci
1047db96d56Sopenharmony_ci#ifdef FAULTHANDLER_USER
1057db96d56Sopenharmony_citypedef struct {
1067db96d56Sopenharmony_ci    int enabled;
1077db96d56Sopenharmony_ci    PyObject *file;
1087db96d56Sopenharmony_ci    int fd;
1097db96d56Sopenharmony_ci    int all_threads;
1107db96d56Sopenharmony_ci    int chain;
1117db96d56Sopenharmony_ci    _Py_sighandler_t previous;
1127db96d56Sopenharmony_ci    PyInterpreterState *interp;
1137db96d56Sopenharmony_ci} user_signal_t;
1147db96d56Sopenharmony_ci
1157db96d56Sopenharmony_cistatic user_signal_t *user_signals;
1167db96d56Sopenharmony_ci
1177db96d56Sopenharmony_cistatic void faulthandler_user(int signum);
1187db96d56Sopenharmony_ci#endif /* FAULTHANDLER_USER */
1197db96d56Sopenharmony_ci
1207db96d56Sopenharmony_ci
1217db96d56Sopenharmony_cistatic fault_handler_t faulthandler_handlers[] = {
1227db96d56Sopenharmony_ci#ifdef SIGBUS
1237db96d56Sopenharmony_ci    {SIGBUS, 0, "Bus error", },
1247db96d56Sopenharmony_ci#endif
1257db96d56Sopenharmony_ci#ifdef SIGILL
1267db96d56Sopenharmony_ci    {SIGILL, 0, "Illegal instruction", },
1277db96d56Sopenharmony_ci#endif
1287db96d56Sopenharmony_ci    {SIGFPE, 0, "Floating point exception", },
1297db96d56Sopenharmony_ci    {SIGABRT, 0, "Aborted", },
1307db96d56Sopenharmony_ci    /* define SIGSEGV at the end to make it the default choice if searching the
1317db96d56Sopenharmony_ci       handler fails in faulthandler_fatal_error() */
1327db96d56Sopenharmony_ci    {SIGSEGV, 0, "Segmentation fault", }
1337db96d56Sopenharmony_ci};
1347db96d56Sopenharmony_cistatic const size_t faulthandler_nsignals = \
1357db96d56Sopenharmony_ci    Py_ARRAY_LENGTH(faulthandler_handlers);
1367db96d56Sopenharmony_ci
1377db96d56Sopenharmony_ci#ifdef FAULTHANDLER_USE_ALT_STACK
1387db96d56Sopenharmony_cistatic stack_t stack;
1397db96d56Sopenharmony_cistatic stack_t old_stack;
1407db96d56Sopenharmony_ci#endif
1417db96d56Sopenharmony_ci
1427db96d56Sopenharmony_ci
1437db96d56Sopenharmony_ci/* Get the file descriptor of a file by calling its fileno() method and then
1447db96d56Sopenharmony_ci   call its flush() method.
1457db96d56Sopenharmony_ci
1467db96d56Sopenharmony_ci   If file is NULL or Py_None, use sys.stderr as the new file.
1477db96d56Sopenharmony_ci   If file is an integer, it will be treated as file descriptor.
1487db96d56Sopenharmony_ci
1497db96d56Sopenharmony_ci   On success, return the file descriptor and write the new file into *file_ptr.
1507db96d56Sopenharmony_ci   On error, return -1. */
1517db96d56Sopenharmony_ci
1527db96d56Sopenharmony_cistatic int
1537db96d56Sopenharmony_cifaulthandler_get_fileno(PyObject **file_ptr)
1547db96d56Sopenharmony_ci{
1557db96d56Sopenharmony_ci    PyObject *result;
1567db96d56Sopenharmony_ci    long fd_long;
1577db96d56Sopenharmony_ci    int fd;
1587db96d56Sopenharmony_ci    PyObject *file = *file_ptr;
1597db96d56Sopenharmony_ci
1607db96d56Sopenharmony_ci    if (file == NULL || file == Py_None) {
1617db96d56Sopenharmony_ci        PyThreadState *tstate = _PyThreadState_GET();
1627db96d56Sopenharmony_ci        file = _PySys_GetAttr(tstate, &_Py_ID(stderr));
1637db96d56Sopenharmony_ci        if (file == NULL) {
1647db96d56Sopenharmony_ci            PyErr_SetString(PyExc_RuntimeError, "unable to get sys.stderr");
1657db96d56Sopenharmony_ci            return -1;
1667db96d56Sopenharmony_ci        }
1677db96d56Sopenharmony_ci        if (file == Py_None) {
1687db96d56Sopenharmony_ci            PyErr_SetString(PyExc_RuntimeError, "sys.stderr is None");
1697db96d56Sopenharmony_ci            return -1;
1707db96d56Sopenharmony_ci        }
1717db96d56Sopenharmony_ci    }
1727db96d56Sopenharmony_ci    else if (PyLong_Check(file)) {
1737db96d56Sopenharmony_ci        fd = _PyLong_AsInt(file);
1747db96d56Sopenharmony_ci        if (fd == -1 && PyErr_Occurred())
1757db96d56Sopenharmony_ci            return -1;
1767db96d56Sopenharmony_ci        if (fd < 0) {
1777db96d56Sopenharmony_ci            PyErr_SetString(PyExc_ValueError,
1787db96d56Sopenharmony_ci                            "file is not a valid file descripter");
1797db96d56Sopenharmony_ci            return -1;
1807db96d56Sopenharmony_ci        }
1817db96d56Sopenharmony_ci        *file_ptr = NULL;
1827db96d56Sopenharmony_ci        return fd;
1837db96d56Sopenharmony_ci    }
1847db96d56Sopenharmony_ci
1857db96d56Sopenharmony_ci    result = PyObject_CallMethodNoArgs(file, &_Py_ID(fileno));
1867db96d56Sopenharmony_ci    if (result == NULL)
1877db96d56Sopenharmony_ci        return -1;
1887db96d56Sopenharmony_ci
1897db96d56Sopenharmony_ci    fd = -1;
1907db96d56Sopenharmony_ci    if (PyLong_Check(result)) {
1917db96d56Sopenharmony_ci        fd_long = PyLong_AsLong(result);
1927db96d56Sopenharmony_ci        if (0 <= fd_long && fd_long < INT_MAX)
1937db96d56Sopenharmony_ci            fd = (int)fd_long;
1947db96d56Sopenharmony_ci    }
1957db96d56Sopenharmony_ci    Py_DECREF(result);
1967db96d56Sopenharmony_ci
1977db96d56Sopenharmony_ci    if (fd == -1) {
1987db96d56Sopenharmony_ci        PyErr_SetString(PyExc_RuntimeError,
1997db96d56Sopenharmony_ci                        "file.fileno() is not a valid file descriptor");
2007db96d56Sopenharmony_ci        return -1;
2017db96d56Sopenharmony_ci    }
2027db96d56Sopenharmony_ci
2037db96d56Sopenharmony_ci    result = PyObject_CallMethodNoArgs(file, &_Py_ID(flush));
2047db96d56Sopenharmony_ci    if (result != NULL)
2057db96d56Sopenharmony_ci        Py_DECREF(result);
2067db96d56Sopenharmony_ci    else {
2077db96d56Sopenharmony_ci        /* ignore flush() error */
2087db96d56Sopenharmony_ci        PyErr_Clear();
2097db96d56Sopenharmony_ci    }
2107db96d56Sopenharmony_ci    *file_ptr = file;
2117db96d56Sopenharmony_ci    return fd;
2127db96d56Sopenharmony_ci}
2137db96d56Sopenharmony_ci
2147db96d56Sopenharmony_ci/* Get the state of the current thread: only call this function if the current
2157db96d56Sopenharmony_ci   thread holds the GIL. Raise an exception on error. */
2167db96d56Sopenharmony_cistatic PyThreadState*
2177db96d56Sopenharmony_ciget_thread_state(void)
2187db96d56Sopenharmony_ci{
2197db96d56Sopenharmony_ci    PyThreadState *tstate = _PyThreadState_GET();
2207db96d56Sopenharmony_ci    if (tstate == NULL) {
2217db96d56Sopenharmony_ci        /* just in case but very unlikely... */
2227db96d56Sopenharmony_ci        PyErr_SetString(PyExc_RuntimeError,
2237db96d56Sopenharmony_ci                        "unable to get the current thread state");
2247db96d56Sopenharmony_ci        return NULL;
2257db96d56Sopenharmony_ci    }
2267db96d56Sopenharmony_ci    return tstate;
2277db96d56Sopenharmony_ci}
2287db96d56Sopenharmony_ci
2297db96d56Sopenharmony_cistatic void
2307db96d56Sopenharmony_cifaulthandler_dump_traceback(int fd, int all_threads,
2317db96d56Sopenharmony_ci                            PyInterpreterState *interp)
2327db96d56Sopenharmony_ci{
2337db96d56Sopenharmony_ci    static volatile int reentrant = 0;
2347db96d56Sopenharmony_ci    PyThreadState *tstate;
2357db96d56Sopenharmony_ci
2367db96d56Sopenharmony_ci    if (reentrant)
2377db96d56Sopenharmony_ci        return;
2387db96d56Sopenharmony_ci
2397db96d56Sopenharmony_ci    reentrant = 1;
2407db96d56Sopenharmony_ci
2417db96d56Sopenharmony_ci    /* SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals and
2427db96d56Sopenharmony_ci       are thus delivered to the thread that caused the fault. Get the Python
2437db96d56Sopenharmony_ci       thread state of the current thread.
2447db96d56Sopenharmony_ci
2457db96d56Sopenharmony_ci       PyThreadState_Get() doesn't give the state of the thread that caused the
2467db96d56Sopenharmony_ci       fault if the thread released the GIL, and so this function cannot be
2477db96d56Sopenharmony_ci       used. Read the thread specific storage (TSS) instead: call
2487db96d56Sopenharmony_ci       PyGILState_GetThisThreadState(). */
2497db96d56Sopenharmony_ci    tstate = PyGILState_GetThisThreadState();
2507db96d56Sopenharmony_ci
2517db96d56Sopenharmony_ci    if (all_threads) {
2527db96d56Sopenharmony_ci        (void)_Py_DumpTracebackThreads(fd, NULL, tstate);
2537db96d56Sopenharmony_ci    }
2547db96d56Sopenharmony_ci    else {
2557db96d56Sopenharmony_ci        if (tstate != NULL)
2567db96d56Sopenharmony_ci            _Py_DumpTraceback(fd, tstate);
2577db96d56Sopenharmony_ci    }
2587db96d56Sopenharmony_ci
2597db96d56Sopenharmony_ci    reentrant = 0;
2607db96d56Sopenharmony_ci}
2617db96d56Sopenharmony_ci
2627db96d56Sopenharmony_cistatic PyObject*
2637db96d56Sopenharmony_cifaulthandler_dump_traceback_py(PyObject *self,
2647db96d56Sopenharmony_ci                               PyObject *args, PyObject *kwargs)
2657db96d56Sopenharmony_ci{
2667db96d56Sopenharmony_ci    static char *kwlist[] = {"file", "all_threads", NULL};
2677db96d56Sopenharmony_ci    PyObject *file = NULL;
2687db96d56Sopenharmony_ci    int all_threads = 1;
2697db96d56Sopenharmony_ci    PyThreadState *tstate;
2707db96d56Sopenharmony_ci    const char *errmsg;
2717db96d56Sopenharmony_ci    int fd;
2727db96d56Sopenharmony_ci
2737db96d56Sopenharmony_ci    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
2747db96d56Sopenharmony_ci        "|Oi:dump_traceback", kwlist,
2757db96d56Sopenharmony_ci        &file, &all_threads))
2767db96d56Sopenharmony_ci        return NULL;
2777db96d56Sopenharmony_ci
2787db96d56Sopenharmony_ci    fd = faulthandler_get_fileno(&file);
2797db96d56Sopenharmony_ci    if (fd < 0)
2807db96d56Sopenharmony_ci        return NULL;
2817db96d56Sopenharmony_ci
2827db96d56Sopenharmony_ci    tstate = get_thread_state();
2837db96d56Sopenharmony_ci    if (tstate == NULL)
2847db96d56Sopenharmony_ci        return NULL;
2857db96d56Sopenharmony_ci
2867db96d56Sopenharmony_ci    if (all_threads) {
2877db96d56Sopenharmony_ci        errmsg = _Py_DumpTracebackThreads(fd, NULL, tstate);
2887db96d56Sopenharmony_ci        if (errmsg != NULL) {
2897db96d56Sopenharmony_ci            PyErr_SetString(PyExc_RuntimeError, errmsg);
2907db96d56Sopenharmony_ci            return NULL;
2917db96d56Sopenharmony_ci        }
2927db96d56Sopenharmony_ci    }
2937db96d56Sopenharmony_ci    else {
2947db96d56Sopenharmony_ci        _Py_DumpTraceback(fd, tstate);
2957db96d56Sopenharmony_ci    }
2967db96d56Sopenharmony_ci
2977db96d56Sopenharmony_ci    if (PyErr_CheckSignals())
2987db96d56Sopenharmony_ci        return NULL;
2997db96d56Sopenharmony_ci
3007db96d56Sopenharmony_ci    Py_RETURN_NONE;
3017db96d56Sopenharmony_ci}
3027db96d56Sopenharmony_ci
3037db96d56Sopenharmony_cistatic void
3047db96d56Sopenharmony_cifaulthandler_disable_fatal_handler(fault_handler_t *handler)
3057db96d56Sopenharmony_ci{
3067db96d56Sopenharmony_ci    if (!handler->enabled)
3077db96d56Sopenharmony_ci        return;
3087db96d56Sopenharmony_ci    handler->enabled = 0;
3097db96d56Sopenharmony_ci#ifdef HAVE_SIGACTION
3107db96d56Sopenharmony_ci    (void)sigaction(handler->signum, &handler->previous, NULL);
3117db96d56Sopenharmony_ci#else
3127db96d56Sopenharmony_ci    (void)signal(handler->signum, handler->previous);
3137db96d56Sopenharmony_ci#endif
3147db96d56Sopenharmony_ci}
3157db96d56Sopenharmony_ci
3167db96d56Sopenharmony_ci
3177db96d56Sopenharmony_ci/* Handler for SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL signals.
3187db96d56Sopenharmony_ci
3197db96d56Sopenharmony_ci   Display the current Python traceback, restore the previous handler and call
3207db96d56Sopenharmony_ci   the previous handler.
3217db96d56Sopenharmony_ci
3227db96d56Sopenharmony_ci   On Windows, don't explicitly call the previous handler, because the Windows
3237db96d56Sopenharmony_ci   signal handler would not be called (for an unknown reason). The execution of
3247db96d56Sopenharmony_ci   the program continues at faulthandler_fatal_error() exit, but the same
3257db96d56Sopenharmony_ci   instruction will raise the same fault (signal), and so the previous handler
3267db96d56Sopenharmony_ci   will be called.
3277db96d56Sopenharmony_ci
3287db96d56Sopenharmony_ci   This function is signal-safe and should only call signal-safe functions. */
3297db96d56Sopenharmony_ci
3307db96d56Sopenharmony_cistatic void
3317db96d56Sopenharmony_cifaulthandler_fatal_error(int signum)
3327db96d56Sopenharmony_ci{
3337db96d56Sopenharmony_ci    const int fd = fatal_error.fd;
3347db96d56Sopenharmony_ci    size_t i;
3357db96d56Sopenharmony_ci    fault_handler_t *handler = NULL;
3367db96d56Sopenharmony_ci    int save_errno = errno;
3377db96d56Sopenharmony_ci    int found = 0;
3387db96d56Sopenharmony_ci
3397db96d56Sopenharmony_ci    if (!fatal_error.enabled)
3407db96d56Sopenharmony_ci        return;
3417db96d56Sopenharmony_ci
3427db96d56Sopenharmony_ci    for (i=0; i < faulthandler_nsignals; i++) {
3437db96d56Sopenharmony_ci        handler = &faulthandler_handlers[i];
3447db96d56Sopenharmony_ci        if (handler->signum == signum) {
3457db96d56Sopenharmony_ci            found = 1;
3467db96d56Sopenharmony_ci            break;
3477db96d56Sopenharmony_ci        }
3487db96d56Sopenharmony_ci    }
3497db96d56Sopenharmony_ci    if (handler == NULL) {
3507db96d56Sopenharmony_ci        /* faulthandler_nsignals == 0 (unlikely) */
3517db96d56Sopenharmony_ci        return;
3527db96d56Sopenharmony_ci    }
3537db96d56Sopenharmony_ci
3547db96d56Sopenharmony_ci    /* restore the previous handler */
3557db96d56Sopenharmony_ci    faulthandler_disable_fatal_handler(handler);
3567db96d56Sopenharmony_ci
3577db96d56Sopenharmony_ci    if (found) {
3587db96d56Sopenharmony_ci        PUTS(fd, "Fatal Python error: ");
3597db96d56Sopenharmony_ci        PUTS(fd, handler->name);
3607db96d56Sopenharmony_ci        PUTS(fd, "\n\n");
3617db96d56Sopenharmony_ci    }
3627db96d56Sopenharmony_ci    else {
3637db96d56Sopenharmony_ci        char unknown_signum[23] = {0,};
3647db96d56Sopenharmony_ci        snprintf(unknown_signum, 23, "%d", signum);
3657db96d56Sopenharmony_ci        PUTS(fd, "Fatal Python error from unexpected signum: ");
3667db96d56Sopenharmony_ci        PUTS(fd, unknown_signum);
3677db96d56Sopenharmony_ci        PUTS(fd, "\n\n");
3687db96d56Sopenharmony_ci    }
3697db96d56Sopenharmony_ci
3707db96d56Sopenharmony_ci    faulthandler_dump_traceback(fd, fatal_error.all_threads,
3717db96d56Sopenharmony_ci                                fatal_error.interp);
3727db96d56Sopenharmony_ci
3737db96d56Sopenharmony_ci    _Py_DumpExtensionModules(fd, fatal_error.interp);
3747db96d56Sopenharmony_ci
3757db96d56Sopenharmony_ci    errno = save_errno;
3767db96d56Sopenharmony_ci#ifdef MS_WINDOWS
3777db96d56Sopenharmony_ci    if (signum == SIGSEGV) {
3787db96d56Sopenharmony_ci        /* don't explicitly call the previous handler for SIGSEGV in this signal
3797db96d56Sopenharmony_ci           handler, because the Windows signal handler would not be called */
3807db96d56Sopenharmony_ci        return;
3817db96d56Sopenharmony_ci    }
3827db96d56Sopenharmony_ci#endif
3837db96d56Sopenharmony_ci    /* call the previous signal handler: it is called immediately if we use
3847db96d56Sopenharmony_ci       sigaction() thanks to SA_NODEFER flag, otherwise it is deferred */
3857db96d56Sopenharmony_ci    raise(signum);
3867db96d56Sopenharmony_ci}
3877db96d56Sopenharmony_ci
3887db96d56Sopenharmony_ci#ifdef MS_WINDOWS
3897db96d56Sopenharmony_cistatic int
3907db96d56Sopenharmony_cifaulthandler_ignore_exception(DWORD code)
3917db96d56Sopenharmony_ci{
3927db96d56Sopenharmony_ci    /* bpo-30557: ignore exceptions which are not errors */
3937db96d56Sopenharmony_ci    if (!(code & 0x80000000)) {
3947db96d56Sopenharmony_ci        return 1;
3957db96d56Sopenharmony_ci    }
3967db96d56Sopenharmony_ci    /* bpo-31701: ignore MSC and COM exceptions
3977db96d56Sopenharmony_ci       E0000000 + code */
3987db96d56Sopenharmony_ci    if (code == 0xE06D7363 /* MSC exception ("Emsc") */
3997db96d56Sopenharmony_ci        || code == 0xE0434352 /* COM Callable Runtime exception ("ECCR") */) {
4007db96d56Sopenharmony_ci        return 1;
4017db96d56Sopenharmony_ci    }
4027db96d56Sopenharmony_ci    /* Interesting exception: log it with the Python traceback */
4037db96d56Sopenharmony_ci    return 0;
4047db96d56Sopenharmony_ci}
4057db96d56Sopenharmony_ci
4067db96d56Sopenharmony_cistatic LONG WINAPI
4077db96d56Sopenharmony_cifaulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info)
4087db96d56Sopenharmony_ci{
4097db96d56Sopenharmony_ci    const int fd = fatal_error.fd;
4107db96d56Sopenharmony_ci    DWORD code = exc_info->ExceptionRecord->ExceptionCode;
4117db96d56Sopenharmony_ci    DWORD flags = exc_info->ExceptionRecord->ExceptionFlags;
4127db96d56Sopenharmony_ci
4137db96d56Sopenharmony_ci    if (faulthandler_ignore_exception(code)) {
4147db96d56Sopenharmony_ci        /* ignore the exception: call the next exception handler */
4157db96d56Sopenharmony_ci        return EXCEPTION_CONTINUE_SEARCH;
4167db96d56Sopenharmony_ci    }
4177db96d56Sopenharmony_ci
4187db96d56Sopenharmony_ci    PUTS(fd, "Windows fatal exception: ");
4197db96d56Sopenharmony_ci    switch (code)
4207db96d56Sopenharmony_ci    {
4217db96d56Sopenharmony_ci    /* only format most common errors */
4227db96d56Sopenharmony_ci    case EXCEPTION_ACCESS_VIOLATION: PUTS(fd, "access violation"); break;
4237db96d56Sopenharmony_ci    case EXCEPTION_FLT_DIVIDE_BY_ZERO: PUTS(fd, "float divide by zero"); break;
4247db96d56Sopenharmony_ci    case EXCEPTION_FLT_OVERFLOW: PUTS(fd, "float overflow"); break;
4257db96d56Sopenharmony_ci    case EXCEPTION_INT_DIVIDE_BY_ZERO: PUTS(fd, "int divide by zero"); break;
4267db96d56Sopenharmony_ci    case EXCEPTION_INT_OVERFLOW: PUTS(fd, "integer overflow"); break;
4277db96d56Sopenharmony_ci    case EXCEPTION_IN_PAGE_ERROR: PUTS(fd, "page error"); break;
4287db96d56Sopenharmony_ci    case EXCEPTION_STACK_OVERFLOW: PUTS(fd, "stack overflow"); break;
4297db96d56Sopenharmony_ci    default:
4307db96d56Sopenharmony_ci        PUTS(fd, "code 0x");
4317db96d56Sopenharmony_ci        _Py_DumpHexadecimal(fd, code, 8);
4327db96d56Sopenharmony_ci    }
4337db96d56Sopenharmony_ci    PUTS(fd, "\n\n");
4347db96d56Sopenharmony_ci
4357db96d56Sopenharmony_ci    if (code == EXCEPTION_ACCESS_VIOLATION) {
4367db96d56Sopenharmony_ci        /* disable signal handler for SIGSEGV */
4377db96d56Sopenharmony_ci        for (size_t i=0; i < faulthandler_nsignals; i++) {
4387db96d56Sopenharmony_ci            fault_handler_t *handler = &faulthandler_handlers[i];
4397db96d56Sopenharmony_ci            if (handler->signum == SIGSEGV) {
4407db96d56Sopenharmony_ci                faulthandler_disable_fatal_handler(handler);
4417db96d56Sopenharmony_ci                break;
4427db96d56Sopenharmony_ci            }
4437db96d56Sopenharmony_ci        }
4447db96d56Sopenharmony_ci    }
4457db96d56Sopenharmony_ci
4467db96d56Sopenharmony_ci    faulthandler_dump_traceback(fd, fatal_error.all_threads,
4477db96d56Sopenharmony_ci                                fatal_error.interp);
4487db96d56Sopenharmony_ci
4497db96d56Sopenharmony_ci    /* call the next exception handler */
4507db96d56Sopenharmony_ci    return EXCEPTION_CONTINUE_SEARCH;
4517db96d56Sopenharmony_ci}
4527db96d56Sopenharmony_ci#endif
4537db96d56Sopenharmony_ci
4547db96d56Sopenharmony_ci
4557db96d56Sopenharmony_ci#ifdef FAULTHANDLER_USE_ALT_STACK
4567db96d56Sopenharmony_cistatic int
4577db96d56Sopenharmony_cifaulthandler_allocate_stack(void)
4587db96d56Sopenharmony_ci{
4597db96d56Sopenharmony_ci    if (stack.ss_sp != NULL) {
4607db96d56Sopenharmony_ci        return 0;
4617db96d56Sopenharmony_ci    }
4627db96d56Sopenharmony_ci    /* Allocate an alternate stack for faulthandler() signal handler
4637db96d56Sopenharmony_ci       to be able to execute a signal handler on a stack overflow error */
4647db96d56Sopenharmony_ci    stack.ss_sp = PyMem_Malloc(stack.ss_size);
4657db96d56Sopenharmony_ci    if (stack.ss_sp == NULL) {
4667db96d56Sopenharmony_ci        PyErr_NoMemory();
4677db96d56Sopenharmony_ci        return -1;
4687db96d56Sopenharmony_ci    }
4697db96d56Sopenharmony_ci
4707db96d56Sopenharmony_ci    int err = sigaltstack(&stack, &old_stack);
4717db96d56Sopenharmony_ci    if (err) {
4727db96d56Sopenharmony_ci        /* Release the stack to retry sigaltstack() next time */
4737db96d56Sopenharmony_ci        PyMem_Free(stack.ss_sp);
4747db96d56Sopenharmony_ci        stack.ss_sp = NULL;
4757db96d56Sopenharmony_ci
4767db96d56Sopenharmony_ci        PyErr_SetFromErrno(PyExc_OSError);
4777db96d56Sopenharmony_ci        return -1;
4787db96d56Sopenharmony_ci    }
4797db96d56Sopenharmony_ci    return 0;
4807db96d56Sopenharmony_ci}
4817db96d56Sopenharmony_ci#endif
4827db96d56Sopenharmony_ci
4837db96d56Sopenharmony_ci
4847db96d56Sopenharmony_ci/* Install the handler for fatal signals, faulthandler_fatal_error(). */
4857db96d56Sopenharmony_ci
4867db96d56Sopenharmony_cistatic int
4877db96d56Sopenharmony_cifaulthandler_enable(void)
4887db96d56Sopenharmony_ci{
4897db96d56Sopenharmony_ci    if (fatal_error.enabled) {
4907db96d56Sopenharmony_ci        return 0;
4917db96d56Sopenharmony_ci    }
4927db96d56Sopenharmony_ci    fatal_error.enabled = 1;
4937db96d56Sopenharmony_ci
4947db96d56Sopenharmony_ci#ifdef FAULTHANDLER_USE_ALT_STACK
4957db96d56Sopenharmony_ci    if (faulthandler_allocate_stack() < 0) {
4967db96d56Sopenharmony_ci        return -1;
4977db96d56Sopenharmony_ci    }
4987db96d56Sopenharmony_ci#endif
4997db96d56Sopenharmony_ci
5007db96d56Sopenharmony_ci    for (size_t i=0; i < faulthandler_nsignals; i++) {
5017db96d56Sopenharmony_ci        fault_handler_t *handler;
5027db96d56Sopenharmony_ci        int err;
5037db96d56Sopenharmony_ci
5047db96d56Sopenharmony_ci        handler = &faulthandler_handlers[i];
5057db96d56Sopenharmony_ci        assert(!handler->enabled);
5067db96d56Sopenharmony_ci#ifdef HAVE_SIGACTION
5077db96d56Sopenharmony_ci        struct sigaction action;
5087db96d56Sopenharmony_ci        action.sa_handler = faulthandler_fatal_error;
5097db96d56Sopenharmony_ci        sigemptyset(&action.sa_mask);
5107db96d56Sopenharmony_ci        /* Do not prevent the signal from being received from within
5117db96d56Sopenharmony_ci           its own signal handler */
5127db96d56Sopenharmony_ci        action.sa_flags = SA_NODEFER;
5137db96d56Sopenharmony_ci#ifdef FAULTHANDLER_USE_ALT_STACK
5147db96d56Sopenharmony_ci        assert(stack.ss_sp != NULL);
5157db96d56Sopenharmony_ci        /* Call the signal handler on an alternate signal stack
5167db96d56Sopenharmony_ci           provided by sigaltstack() */
5177db96d56Sopenharmony_ci        action.sa_flags |= SA_ONSTACK;
5187db96d56Sopenharmony_ci#endif
5197db96d56Sopenharmony_ci        err = sigaction(handler->signum, &action, &handler->previous);
5207db96d56Sopenharmony_ci#else
5217db96d56Sopenharmony_ci        handler->previous = signal(handler->signum,
5227db96d56Sopenharmony_ci                                   faulthandler_fatal_error);
5237db96d56Sopenharmony_ci        err = (handler->previous == SIG_ERR);
5247db96d56Sopenharmony_ci#endif
5257db96d56Sopenharmony_ci        if (err) {
5267db96d56Sopenharmony_ci            PyErr_SetFromErrno(PyExc_RuntimeError);
5277db96d56Sopenharmony_ci            return -1;
5287db96d56Sopenharmony_ci        }
5297db96d56Sopenharmony_ci
5307db96d56Sopenharmony_ci        handler->enabled = 1;
5317db96d56Sopenharmony_ci    }
5327db96d56Sopenharmony_ci
5337db96d56Sopenharmony_ci#ifdef MS_WINDOWS
5347db96d56Sopenharmony_ci    assert(fatal_error.exc_handler == NULL);
5357db96d56Sopenharmony_ci    fatal_error.exc_handler = AddVectoredExceptionHandler(1, faulthandler_exc_handler);
5367db96d56Sopenharmony_ci#endif
5377db96d56Sopenharmony_ci    return 0;
5387db96d56Sopenharmony_ci}
5397db96d56Sopenharmony_ci
5407db96d56Sopenharmony_cistatic PyObject*
5417db96d56Sopenharmony_cifaulthandler_py_enable(PyObject *self, PyObject *args, PyObject *kwargs)
5427db96d56Sopenharmony_ci{
5437db96d56Sopenharmony_ci    static char *kwlist[] = {"file", "all_threads", NULL};
5447db96d56Sopenharmony_ci    PyObject *file = NULL;
5457db96d56Sopenharmony_ci    int all_threads = 1;
5467db96d56Sopenharmony_ci    int fd;
5477db96d56Sopenharmony_ci    PyThreadState *tstate;
5487db96d56Sopenharmony_ci
5497db96d56Sopenharmony_ci    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5507db96d56Sopenharmony_ci        "|Oi:enable", kwlist, &file, &all_threads))
5517db96d56Sopenharmony_ci        return NULL;
5527db96d56Sopenharmony_ci
5537db96d56Sopenharmony_ci    fd = faulthandler_get_fileno(&file);
5547db96d56Sopenharmony_ci    if (fd < 0)
5557db96d56Sopenharmony_ci        return NULL;
5567db96d56Sopenharmony_ci
5577db96d56Sopenharmony_ci    tstate = get_thread_state();
5587db96d56Sopenharmony_ci    if (tstate == NULL)
5597db96d56Sopenharmony_ci        return NULL;
5607db96d56Sopenharmony_ci
5617db96d56Sopenharmony_ci    Py_XINCREF(file);
5627db96d56Sopenharmony_ci    Py_XSETREF(fatal_error.file, file);
5637db96d56Sopenharmony_ci    fatal_error.fd = fd;
5647db96d56Sopenharmony_ci    fatal_error.all_threads = all_threads;
5657db96d56Sopenharmony_ci    fatal_error.interp = PyThreadState_GetInterpreter(tstate);
5667db96d56Sopenharmony_ci
5677db96d56Sopenharmony_ci    if (faulthandler_enable() < 0) {
5687db96d56Sopenharmony_ci        return NULL;
5697db96d56Sopenharmony_ci    }
5707db96d56Sopenharmony_ci
5717db96d56Sopenharmony_ci    Py_RETURN_NONE;
5727db96d56Sopenharmony_ci}
5737db96d56Sopenharmony_ci
5747db96d56Sopenharmony_cistatic void
5757db96d56Sopenharmony_cifaulthandler_disable(void)
5767db96d56Sopenharmony_ci{
5777db96d56Sopenharmony_ci    if (fatal_error.enabled) {
5787db96d56Sopenharmony_ci        fatal_error.enabled = 0;
5797db96d56Sopenharmony_ci        for (size_t i=0; i < faulthandler_nsignals; i++) {
5807db96d56Sopenharmony_ci            fault_handler_t *handler;
5817db96d56Sopenharmony_ci            handler = &faulthandler_handlers[i];
5827db96d56Sopenharmony_ci            faulthandler_disable_fatal_handler(handler);
5837db96d56Sopenharmony_ci        }
5847db96d56Sopenharmony_ci    }
5857db96d56Sopenharmony_ci#ifdef MS_WINDOWS
5867db96d56Sopenharmony_ci    if (fatal_error.exc_handler != NULL) {
5877db96d56Sopenharmony_ci        RemoveVectoredExceptionHandler(fatal_error.exc_handler);
5887db96d56Sopenharmony_ci        fatal_error.exc_handler = NULL;
5897db96d56Sopenharmony_ci    }
5907db96d56Sopenharmony_ci#endif
5917db96d56Sopenharmony_ci    Py_CLEAR(fatal_error.file);
5927db96d56Sopenharmony_ci}
5937db96d56Sopenharmony_ci
5947db96d56Sopenharmony_cistatic PyObject*
5957db96d56Sopenharmony_cifaulthandler_disable_py(PyObject *self, PyObject *Py_UNUSED(ignored))
5967db96d56Sopenharmony_ci{
5977db96d56Sopenharmony_ci    if (!fatal_error.enabled) {
5987db96d56Sopenharmony_ci        Py_RETURN_FALSE;
5997db96d56Sopenharmony_ci    }
6007db96d56Sopenharmony_ci    faulthandler_disable();
6017db96d56Sopenharmony_ci    Py_RETURN_TRUE;
6027db96d56Sopenharmony_ci}
6037db96d56Sopenharmony_ci
6047db96d56Sopenharmony_cistatic PyObject*
6057db96d56Sopenharmony_cifaulthandler_is_enabled(PyObject *self, PyObject *Py_UNUSED(ignored))
6067db96d56Sopenharmony_ci{
6077db96d56Sopenharmony_ci    return PyBool_FromLong(fatal_error.enabled);
6087db96d56Sopenharmony_ci}
6097db96d56Sopenharmony_ci
6107db96d56Sopenharmony_cistatic void
6117db96d56Sopenharmony_cifaulthandler_thread(void *unused)
6127db96d56Sopenharmony_ci{
6137db96d56Sopenharmony_ci    PyLockStatus st;
6147db96d56Sopenharmony_ci    const char* errmsg;
6157db96d56Sopenharmony_ci    int ok;
6167db96d56Sopenharmony_ci#if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK)
6177db96d56Sopenharmony_ci    sigset_t set;
6187db96d56Sopenharmony_ci
6197db96d56Sopenharmony_ci    /* we don't want to receive any signal */
6207db96d56Sopenharmony_ci    sigfillset(&set);
6217db96d56Sopenharmony_ci    pthread_sigmask(SIG_SETMASK, &set, NULL);
6227db96d56Sopenharmony_ci#endif
6237db96d56Sopenharmony_ci
6247db96d56Sopenharmony_ci    do {
6257db96d56Sopenharmony_ci        st = PyThread_acquire_lock_timed(thread.cancel_event,
6267db96d56Sopenharmony_ci                                         thread.timeout_us, 0);
6277db96d56Sopenharmony_ci        if (st == PY_LOCK_ACQUIRED) {
6287db96d56Sopenharmony_ci            PyThread_release_lock(thread.cancel_event);
6297db96d56Sopenharmony_ci            break;
6307db96d56Sopenharmony_ci        }
6317db96d56Sopenharmony_ci        /* Timeout => dump traceback */
6327db96d56Sopenharmony_ci        assert(st == PY_LOCK_FAILURE);
6337db96d56Sopenharmony_ci
6347db96d56Sopenharmony_ci        _Py_write_noraise(thread.fd, thread.header, (int)thread.header_len);
6357db96d56Sopenharmony_ci
6367db96d56Sopenharmony_ci        errmsg = _Py_DumpTracebackThreads(thread.fd, thread.interp, NULL);
6377db96d56Sopenharmony_ci        ok = (errmsg == NULL);
6387db96d56Sopenharmony_ci
6397db96d56Sopenharmony_ci        if (thread.exit)
6407db96d56Sopenharmony_ci            _exit(1);
6417db96d56Sopenharmony_ci    } while (ok && thread.repeat);
6427db96d56Sopenharmony_ci
6437db96d56Sopenharmony_ci    /* The only way out */
6447db96d56Sopenharmony_ci    PyThread_release_lock(thread.running);
6457db96d56Sopenharmony_ci}
6467db96d56Sopenharmony_ci
6477db96d56Sopenharmony_cistatic void
6487db96d56Sopenharmony_cicancel_dump_traceback_later(void)
6497db96d56Sopenharmony_ci{
6507db96d56Sopenharmony_ci    /* If not scheduled, nothing to cancel */
6517db96d56Sopenharmony_ci    if (!thread.cancel_event) {
6527db96d56Sopenharmony_ci        return;
6537db96d56Sopenharmony_ci    }
6547db96d56Sopenharmony_ci
6557db96d56Sopenharmony_ci    /* Notify cancellation */
6567db96d56Sopenharmony_ci    PyThread_release_lock(thread.cancel_event);
6577db96d56Sopenharmony_ci
6587db96d56Sopenharmony_ci    /* Wait for thread to join */
6597db96d56Sopenharmony_ci    PyThread_acquire_lock(thread.running, 1);
6607db96d56Sopenharmony_ci    PyThread_release_lock(thread.running);
6617db96d56Sopenharmony_ci
6627db96d56Sopenharmony_ci    /* The main thread should always hold the cancel_event lock */
6637db96d56Sopenharmony_ci    PyThread_acquire_lock(thread.cancel_event, 1);
6647db96d56Sopenharmony_ci
6657db96d56Sopenharmony_ci    Py_CLEAR(thread.file);
6667db96d56Sopenharmony_ci    if (thread.header) {
6677db96d56Sopenharmony_ci        PyMem_Free(thread.header);
6687db96d56Sopenharmony_ci        thread.header = NULL;
6697db96d56Sopenharmony_ci    }
6707db96d56Sopenharmony_ci}
6717db96d56Sopenharmony_ci
6727db96d56Sopenharmony_ci#define SEC_TO_US (1000 * 1000)
6737db96d56Sopenharmony_ci
6747db96d56Sopenharmony_cistatic char*
6757db96d56Sopenharmony_ciformat_timeout(_PyTime_t us)
6767db96d56Sopenharmony_ci{
6777db96d56Sopenharmony_ci    unsigned long sec, min, hour;
6787db96d56Sopenharmony_ci    char buffer[100];
6797db96d56Sopenharmony_ci
6807db96d56Sopenharmony_ci    /* the downcast is safe: the caller check that 0 < us <= LONG_MAX */
6817db96d56Sopenharmony_ci    sec = (unsigned long)(us / SEC_TO_US);
6827db96d56Sopenharmony_ci    us %= SEC_TO_US;
6837db96d56Sopenharmony_ci
6847db96d56Sopenharmony_ci    min = sec / 60;
6857db96d56Sopenharmony_ci    sec %= 60;
6867db96d56Sopenharmony_ci    hour = min / 60;
6877db96d56Sopenharmony_ci    min %= 60;
6887db96d56Sopenharmony_ci
6897db96d56Sopenharmony_ci    if (us != 0) {
6907db96d56Sopenharmony_ci        PyOS_snprintf(buffer, sizeof(buffer),
6917db96d56Sopenharmony_ci                      "Timeout (%lu:%02lu:%02lu.%06u)!\n",
6927db96d56Sopenharmony_ci                      hour, min, sec, (unsigned int)us);
6937db96d56Sopenharmony_ci    }
6947db96d56Sopenharmony_ci    else {
6957db96d56Sopenharmony_ci        PyOS_snprintf(buffer, sizeof(buffer),
6967db96d56Sopenharmony_ci                      "Timeout (%lu:%02lu:%02lu)!\n",
6977db96d56Sopenharmony_ci                      hour, min, sec);
6987db96d56Sopenharmony_ci    }
6997db96d56Sopenharmony_ci    return _PyMem_Strdup(buffer);
7007db96d56Sopenharmony_ci}
7017db96d56Sopenharmony_ci
7027db96d56Sopenharmony_cistatic PyObject*
7037db96d56Sopenharmony_cifaulthandler_dump_traceback_later(PyObject *self,
7047db96d56Sopenharmony_ci                                   PyObject *args, PyObject *kwargs)
7057db96d56Sopenharmony_ci{
7067db96d56Sopenharmony_ci    static char *kwlist[] = {"timeout", "repeat", "file", "exit", NULL};
7077db96d56Sopenharmony_ci    PyObject *timeout_obj;
7087db96d56Sopenharmony_ci    _PyTime_t timeout, timeout_us;
7097db96d56Sopenharmony_ci    int repeat = 0;
7107db96d56Sopenharmony_ci    PyObject *file = NULL;
7117db96d56Sopenharmony_ci    int fd;
7127db96d56Sopenharmony_ci    int exit = 0;
7137db96d56Sopenharmony_ci    PyThreadState *tstate;
7147db96d56Sopenharmony_ci    char *header;
7157db96d56Sopenharmony_ci    size_t header_len;
7167db96d56Sopenharmony_ci
7177db96d56Sopenharmony_ci    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
7187db96d56Sopenharmony_ci        "O|iOi:dump_traceback_later", kwlist,
7197db96d56Sopenharmony_ci        &timeout_obj, &repeat, &file, &exit))
7207db96d56Sopenharmony_ci        return NULL;
7217db96d56Sopenharmony_ci
7227db96d56Sopenharmony_ci    if (_PyTime_FromSecondsObject(&timeout, timeout_obj,
7237db96d56Sopenharmony_ci                                  _PyTime_ROUND_TIMEOUT) < 0) {
7247db96d56Sopenharmony_ci        return NULL;
7257db96d56Sopenharmony_ci    }
7267db96d56Sopenharmony_ci    timeout_us = _PyTime_AsMicroseconds(timeout, _PyTime_ROUND_TIMEOUT);
7277db96d56Sopenharmony_ci    if (timeout_us <= 0) {
7287db96d56Sopenharmony_ci        PyErr_SetString(PyExc_ValueError, "timeout must be greater than 0");
7297db96d56Sopenharmony_ci        return NULL;
7307db96d56Sopenharmony_ci    }
7317db96d56Sopenharmony_ci    /* Limit to LONG_MAX seconds for format_timeout() */
7327db96d56Sopenharmony_ci    if (timeout_us > PY_TIMEOUT_MAX || timeout_us / SEC_TO_US > LONG_MAX) {
7337db96d56Sopenharmony_ci        PyErr_SetString(PyExc_OverflowError,
7347db96d56Sopenharmony_ci                        "timeout value is too large");
7357db96d56Sopenharmony_ci        return NULL;
7367db96d56Sopenharmony_ci    }
7377db96d56Sopenharmony_ci
7387db96d56Sopenharmony_ci    tstate = get_thread_state();
7397db96d56Sopenharmony_ci    if (tstate == NULL) {
7407db96d56Sopenharmony_ci        return NULL;
7417db96d56Sopenharmony_ci    }
7427db96d56Sopenharmony_ci
7437db96d56Sopenharmony_ci    fd = faulthandler_get_fileno(&file);
7447db96d56Sopenharmony_ci    if (fd < 0) {
7457db96d56Sopenharmony_ci        return NULL;
7467db96d56Sopenharmony_ci    }
7477db96d56Sopenharmony_ci
7487db96d56Sopenharmony_ci    if (!thread.running) {
7497db96d56Sopenharmony_ci        thread.running = PyThread_allocate_lock();
7507db96d56Sopenharmony_ci        if (!thread.running) {
7517db96d56Sopenharmony_ci            return PyErr_NoMemory();
7527db96d56Sopenharmony_ci        }
7537db96d56Sopenharmony_ci    }
7547db96d56Sopenharmony_ci    if (!thread.cancel_event) {
7557db96d56Sopenharmony_ci        thread.cancel_event = PyThread_allocate_lock();
7567db96d56Sopenharmony_ci        if (!thread.cancel_event || !thread.running) {
7577db96d56Sopenharmony_ci            return PyErr_NoMemory();
7587db96d56Sopenharmony_ci        }
7597db96d56Sopenharmony_ci
7607db96d56Sopenharmony_ci        /* cancel_event starts to be acquired: it's only released to cancel
7617db96d56Sopenharmony_ci           the thread. */
7627db96d56Sopenharmony_ci        PyThread_acquire_lock(thread.cancel_event, 1);
7637db96d56Sopenharmony_ci    }
7647db96d56Sopenharmony_ci
7657db96d56Sopenharmony_ci    /* format the timeout */
7667db96d56Sopenharmony_ci    header = format_timeout(timeout_us);
7677db96d56Sopenharmony_ci    if (header == NULL) {
7687db96d56Sopenharmony_ci        return PyErr_NoMemory();
7697db96d56Sopenharmony_ci    }
7707db96d56Sopenharmony_ci    header_len = strlen(header);
7717db96d56Sopenharmony_ci
7727db96d56Sopenharmony_ci    /* Cancel previous thread, if running */
7737db96d56Sopenharmony_ci    cancel_dump_traceback_later();
7747db96d56Sopenharmony_ci
7757db96d56Sopenharmony_ci    Py_XINCREF(file);
7767db96d56Sopenharmony_ci    Py_XSETREF(thread.file, file);
7777db96d56Sopenharmony_ci    thread.fd = fd;
7787db96d56Sopenharmony_ci    /* the downcast is safe: we check that 0 < timeout_us < PY_TIMEOUT_MAX */
7797db96d56Sopenharmony_ci    thread.timeout_us = (PY_TIMEOUT_T)timeout_us;
7807db96d56Sopenharmony_ci    thread.repeat = repeat;
7817db96d56Sopenharmony_ci    thread.interp = PyThreadState_GetInterpreter(tstate);
7827db96d56Sopenharmony_ci    thread.exit = exit;
7837db96d56Sopenharmony_ci    thread.header = header;
7847db96d56Sopenharmony_ci    thread.header_len = header_len;
7857db96d56Sopenharmony_ci
7867db96d56Sopenharmony_ci    /* Arm these locks to serve as events when released */
7877db96d56Sopenharmony_ci    PyThread_acquire_lock(thread.running, 1);
7887db96d56Sopenharmony_ci
7897db96d56Sopenharmony_ci    if (PyThread_start_new_thread(faulthandler_thread, NULL) == PYTHREAD_INVALID_THREAD_ID) {
7907db96d56Sopenharmony_ci        PyThread_release_lock(thread.running);
7917db96d56Sopenharmony_ci        Py_CLEAR(thread.file);
7927db96d56Sopenharmony_ci        PyMem_Free(header);
7937db96d56Sopenharmony_ci        thread.header = NULL;
7947db96d56Sopenharmony_ci        PyErr_SetString(PyExc_RuntimeError,
7957db96d56Sopenharmony_ci                        "unable to start watchdog thread");
7967db96d56Sopenharmony_ci        return NULL;
7977db96d56Sopenharmony_ci    }
7987db96d56Sopenharmony_ci
7997db96d56Sopenharmony_ci    Py_RETURN_NONE;
8007db96d56Sopenharmony_ci}
8017db96d56Sopenharmony_ci
8027db96d56Sopenharmony_cistatic PyObject*
8037db96d56Sopenharmony_cifaulthandler_cancel_dump_traceback_later_py(PyObject *self,
8047db96d56Sopenharmony_ci                                            PyObject *Py_UNUSED(ignored))
8057db96d56Sopenharmony_ci{
8067db96d56Sopenharmony_ci    cancel_dump_traceback_later();
8077db96d56Sopenharmony_ci    Py_RETURN_NONE;
8087db96d56Sopenharmony_ci}
8097db96d56Sopenharmony_ci
8107db96d56Sopenharmony_ci
8117db96d56Sopenharmony_ci#ifdef FAULTHANDLER_USER
8127db96d56Sopenharmony_cistatic int
8137db96d56Sopenharmony_cifaulthandler_register(int signum, int chain, _Py_sighandler_t *previous_p)
8147db96d56Sopenharmony_ci{
8157db96d56Sopenharmony_ci#ifdef HAVE_SIGACTION
8167db96d56Sopenharmony_ci    struct sigaction action;
8177db96d56Sopenharmony_ci    action.sa_handler = faulthandler_user;
8187db96d56Sopenharmony_ci    sigemptyset(&action.sa_mask);
8197db96d56Sopenharmony_ci    /* if the signal is received while the kernel is executing a system
8207db96d56Sopenharmony_ci       call, try to restart the system call instead of interrupting it and
8217db96d56Sopenharmony_ci       return EINTR. */
8227db96d56Sopenharmony_ci    action.sa_flags = SA_RESTART;
8237db96d56Sopenharmony_ci    if (chain) {
8247db96d56Sopenharmony_ci        /* do not prevent the signal from being received from within its
8257db96d56Sopenharmony_ci           own signal handler */
8267db96d56Sopenharmony_ci        action.sa_flags = SA_NODEFER;
8277db96d56Sopenharmony_ci    }
8287db96d56Sopenharmony_ci#ifdef FAULTHANDLER_USE_ALT_STACK
8297db96d56Sopenharmony_ci    assert(stack.ss_sp != NULL);
8307db96d56Sopenharmony_ci    /* Call the signal handler on an alternate signal stack
8317db96d56Sopenharmony_ci       provided by sigaltstack() */
8327db96d56Sopenharmony_ci    action.sa_flags |= SA_ONSTACK;
8337db96d56Sopenharmony_ci#endif
8347db96d56Sopenharmony_ci    return sigaction(signum, &action, previous_p);
8357db96d56Sopenharmony_ci#else
8367db96d56Sopenharmony_ci    _Py_sighandler_t previous;
8377db96d56Sopenharmony_ci    previous = signal(signum, faulthandler_user);
8387db96d56Sopenharmony_ci    if (previous_p != NULL) {
8397db96d56Sopenharmony_ci        *previous_p = previous;
8407db96d56Sopenharmony_ci    }
8417db96d56Sopenharmony_ci    return (previous == SIG_ERR);
8427db96d56Sopenharmony_ci#endif
8437db96d56Sopenharmony_ci}
8447db96d56Sopenharmony_ci
8457db96d56Sopenharmony_ci/* Handler of user signals (e.g. SIGUSR1).
8467db96d56Sopenharmony_ci
8477db96d56Sopenharmony_ci   Dump the traceback of the current thread, or of all threads if
8487db96d56Sopenharmony_ci   thread.all_threads is true.
8497db96d56Sopenharmony_ci
8507db96d56Sopenharmony_ci   This function is signal safe and should only call signal safe functions. */
8517db96d56Sopenharmony_ci
8527db96d56Sopenharmony_cistatic void
8537db96d56Sopenharmony_cifaulthandler_user(int signum)
8547db96d56Sopenharmony_ci{
8557db96d56Sopenharmony_ci    user_signal_t *user;
8567db96d56Sopenharmony_ci    int save_errno = errno;
8577db96d56Sopenharmony_ci
8587db96d56Sopenharmony_ci    user = &user_signals[signum];
8597db96d56Sopenharmony_ci    if (!user->enabled)
8607db96d56Sopenharmony_ci        return;
8617db96d56Sopenharmony_ci
8627db96d56Sopenharmony_ci    faulthandler_dump_traceback(user->fd, user->all_threads, user->interp);
8637db96d56Sopenharmony_ci
8647db96d56Sopenharmony_ci#ifdef HAVE_SIGACTION
8657db96d56Sopenharmony_ci    if (user->chain) {
8667db96d56Sopenharmony_ci        (void)sigaction(signum, &user->previous, NULL);
8677db96d56Sopenharmony_ci        errno = save_errno;
8687db96d56Sopenharmony_ci
8697db96d56Sopenharmony_ci        /* call the previous signal handler */
8707db96d56Sopenharmony_ci        raise(signum);
8717db96d56Sopenharmony_ci
8727db96d56Sopenharmony_ci        save_errno = errno;
8737db96d56Sopenharmony_ci        (void)faulthandler_register(signum, user->chain, NULL);
8747db96d56Sopenharmony_ci        errno = save_errno;
8757db96d56Sopenharmony_ci    }
8767db96d56Sopenharmony_ci#else
8777db96d56Sopenharmony_ci    if (user->chain && user->previous != NULL) {
8787db96d56Sopenharmony_ci        errno = save_errno;
8797db96d56Sopenharmony_ci        /* call the previous signal handler */
8807db96d56Sopenharmony_ci        user->previous(signum);
8817db96d56Sopenharmony_ci    }
8827db96d56Sopenharmony_ci#endif
8837db96d56Sopenharmony_ci}
8847db96d56Sopenharmony_ci
8857db96d56Sopenharmony_cistatic int
8867db96d56Sopenharmony_cicheck_signum(int signum)
8877db96d56Sopenharmony_ci{
8887db96d56Sopenharmony_ci    for (size_t i=0; i < faulthandler_nsignals; i++) {
8897db96d56Sopenharmony_ci        if (faulthandler_handlers[i].signum == signum) {
8907db96d56Sopenharmony_ci            PyErr_Format(PyExc_RuntimeError,
8917db96d56Sopenharmony_ci                         "signal %i cannot be registered, "
8927db96d56Sopenharmony_ci                         "use enable() instead",
8937db96d56Sopenharmony_ci                         signum);
8947db96d56Sopenharmony_ci            return 0;
8957db96d56Sopenharmony_ci        }
8967db96d56Sopenharmony_ci    }
8977db96d56Sopenharmony_ci    if (signum < 1 || Py_NSIG <= signum) {
8987db96d56Sopenharmony_ci        PyErr_SetString(PyExc_ValueError, "signal number out of range");
8997db96d56Sopenharmony_ci        return 0;
9007db96d56Sopenharmony_ci    }
9017db96d56Sopenharmony_ci    return 1;
9027db96d56Sopenharmony_ci}
9037db96d56Sopenharmony_ci
9047db96d56Sopenharmony_cistatic PyObject*
9057db96d56Sopenharmony_cifaulthandler_register_py(PyObject *self,
9067db96d56Sopenharmony_ci                         PyObject *args, PyObject *kwargs)
9077db96d56Sopenharmony_ci{
9087db96d56Sopenharmony_ci    static char *kwlist[] = {"signum", "file", "all_threads", "chain", NULL};
9097db96d56Sopenharmony_ci    int signum;
9107db96d56Sopenharmony_ci    PyObject *file = NULL;
9117db96d56Sopenharmony_ci    int all_threads = 1;
9127db96d56Sopenharmony_ci    int chain = 0;
9137db96d56Sopenharmony_ci    int fd;
9147db96d56Sopenharmony_ci    user_signal_t *user;
9157db96d56Sopenharmony_ci    _Py_sighandler_t previous;
9167db96d56Sopenharmony_ci    PyThreadState *tstate;
9177db96d56Sopenharmony_ci    int err;
9187db96d56Sopenharmony_ci
9197db96d56Sopenharmony_ci    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
9207db96d56Sopenharmony_ci        "i|Oii:register", kwlist,
9217db96d56Sopenharmony_ci        &signum, &file, &all_threads, &chain))
9227db96d56Sopenharmony_ci        return NULL;
9237db96d56Sopenharmony_ci
9247db96d56Sopenharmony_ci    if (!check_signum(signum))
9257db96d56Sopenharmony_ci        return NULL;
9267db96d56Sopenharmony_ci
9277db96d56Sopenharmony_ci    tstate = get_thread_state();
9287db96d56Sopenharmony_ci    if (tstate == NULL)
9297db96d56Sopenharmony_ci        return NULL;
9307db96d56Sopenharmony_ci
9317db96d56Sopenharmony_ci    fd = faulthandler_get_fileno(&file);
9327db96d56Sopenharmony_ci    if (fd < 0)
9337db96d56Sopenharmony_ci        return NULL;
9347db96d56Sopenharmony_ci
9357db96d56Sopenharmony_ci    if (user_signals == NULL) {
9367db96d56Sopenharmony_ci        user_signals = PyMem_Calloc(Py_NSIG, sizeof(user_signal_t));
9377db96d56Sopenharmony_ci        if (user_signals == NULL)
9387db96d56Sopenharmony_ci            return PyErr_NoMemory();
9397db96d56Sopenharmony_ci    }
9407db96d56Sopenharmony_ci    user = &user_signals[signum];
9417db96d56Sopenharmony_ci
9427db96d56Sopenharmony_ci    if (!user->enabled) {
9437db96d56Sopenharmony_ci#ifdef FAULTHANDLER_USE_ALT_STACK
9447db96d56Sopenharmony_ci        if (faulthandler_allocate_stack() < 0) {
9457db96d56Sopenharmony_ci            return NULL;
9467db96d56Sopenharmony_ci        }
9477db96d56Sopenharmony_ci#endif
9487db96d56Sopenharmony_ci
9497db96d56Sopenharmony_ci        err = faulthandler_register(signum, chain, &previous);
9507db96d56Sopenharmony_ci        if (err) {
9517db96d56Sopenharmony_ci            PyErr_SetFromErrno(PyExc_OSError);
9527db96d56Sopenharmony_ci            return NULL;
9537db96d56Sopenharmony_ci        }
9547db96d56Sopenharmony_ci
9557db96d56Sopenharmony_ci        user->previous = previous;
9567db96d56Sopenharmony_ci    }
9577db96d56Sopenharmony_ci
9587db96d56Sopenharmony_ci    Py_XINCREF(file);
9597db96d56Sopenharmony_ci    Py_XSETREF(user->file, file);
9607db96d56Sopenharmony_ci    user->fd = fd;
9617db96d56Sopenharmony_ci    user->all_threads = all_threads;
9627db96d56Sopenharmony_ci    user->chain = chain;
9637db96d56Sopenharmony_ci    user->interp = PyThreadState_GetInterpreter(tstate);
9647db96d56Sopenharmony_ci    user->enabled = 1;
9657db96d56Sopenharmony_ci
9667db96d56Sopenharmony_ci    Py_RETURN_NONE;
9677db96d56Sopenharmony_ci}
9687db96d56Sopenharmony_ci
9697db96d56Sopenharmony_cistatic int
9707db96d56Sopenharmony_cifaulthandler_unregister(user_signal_t *user, int signum)
9717db96d56Sopenharmony_ci{
9727db96d56Sopenharmony_ci    if (!user->enabled)
9737db96d56Sopenharmony_ci        return 0;
9747db96d56Sopenharmony_ci    user->enabled = 0;
9757db96d56Sopenharmony_ci#ifdef HAVE_SIGACTION
9767db96d56Sopenharmony_ci    (void)sigaction(signum, &user->previous, NULL);
9777db96d56Sopenharmony_ci#else
9787db96d56Sopenharmony_ci    (void)signal(signum, user->previous);
9797db96d56Sopenharmony_ci#endif
9807db96d56Sopenharmony_ci    Py_CLEAR(user->file);
9817db96d56Sopenharmony_ci    user->fd = -1;
9827db96d56Sopenharmony_ci    return 1;
9837db96d56Sopenharmony_ci}
9847db96d56Sopenharmony_ci
9857db96d56Sopenharmony_cistatic PyObject*
9867db96d56Sopenharmony_cifaulthandler_unregister_py(PyObject *self, PyObject *args)
9877db96d56Sopenharmony_ci{
9887db96d56Sopenharmony_ci    int signum;
9897db96d56Sopenharmony_ci    user_signal_t *user;
9907db96d56Sopenharmony_ci    int change;
9917db96d56Sopenharmony_ci
9927db96d56Sopenharmony_ci    if (!PyArg_ParseTuple(args, "i:unregister", &signum))
9937db96d56Sopenharmony_ci        return NULL;
9947db96d56Sopenharmony_ci
9957db96d56Sopenharmony_ci    if (!check_signum(signum))
9967db96d56Sopenharmony_ci        return NULL;
9977db96d56Sopenharmony_ci
9987db96d56Sopenharmony_ci    if (user_signals == NULL)
9997db96d56Sopenharmony_ci        Py_RETURN_FALSE;
10007db96d56Sopenharmony_ci
10017db96d56Sopenharmony_ci    user = &user_signals[signum];
10027db96d56Sopenharmony_ci    change = faulthandler_unregister(user, signum);
10037db96d56Sopenharmony_ci    return PyBool_FromLong(change);
10047db96d56Sopenharmony_ci}
10057db96d56Sopenharmony_ci#endif   /* FAULTHANDLER_USER */
10067db96d56Sopenharmony_ci
10077db96d56Sopenharmony_ci
10087db96d56Sopenharmony_cistatic void
10097db96d56Sopenharmony_cifaulthandler_suppress_crash_report(void)
10107db96d56Sopenharmony_ci{
10117db96d56Sopenharmony_ci#ifdef MS_WINDOWS
10127db96d56Sopenharmony_ci    UINT mode;
10137db96d56Sopenharmony_ci
10147db96d56Sopenharmony_ci    /* Configure Windows to not display the Windows Error Reporting dialog */
10157db96d56Sopenharmony_ci    mode = SetErrorMode(SEM_NOGPFAULTERRORBOX);
10167db96d56Sopenharmony_ci    SetErrorMode(mode | SEM_NOGPFAULTERRORBOX);
10177db96d56Sopenharmony_ci#endif
10187db96d56Sopenharmony_ci
10197db96d56Sopenharmony_ci#ifdef HAVE_SYS_RESOURCE_H
10207db96d56Sopenharmony_ci    struct rlimit rl;
10217db96d56Sopenharmony_ci
10227db96d56Sopenharmony_ci    /* Disable creation of core dump */
10237db96d56Sopenharmony_ci    if (getrlimit(RLIMIT_CORE, &rl) == 0) {
10247db96d56Sopenharmony_ci        rl.rlim_cur = 0;
10257db96d56Sopenharmony_ci        setrlimit(RLIMIT_CORE, &rl);
10267db96d56Sopenharmony_ci    }
10277db96d56Sopenharmony_ci#endif
10287db96d56Sopenharmony_ci
10297db96d56Sopenharmony_ci#ifdef _MSC_VER
10307db96d56Sopenharmony_ci    /* Visual Studio: configure abort() to not display an error message nor
10317db96d56Sopenharmony_ci       open a popup asking to report the fault. */
10327db96d56Sopenharmony_ci    _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
10337db96d56Sopenharmony_ci#endif
10347db96d56Sopenharmony_ci}
10357db96d56Sopenharmony_ci
10367db96d56Sopenharmony_cistatic PyObject* _Py_NO_SANITIZE_UNDEFINED
10377db96d56Sopenharmony_cifaulthandler_read_null(PyObject *self, PyObject *args)
10387db96d56Sopenharmony_ci{
10397db96d56Sopenharmony_ci    volatile int *x;
10407db96d56Sopenharmony_ci    volatile int y;
10417db96d56Sopenharmony_ci
10427db96d56Sopenharmony_ci    faulthandler_suppress_crash_report();
10437db96d56Sopenharmony_ci    x = NULL;
10447db96d56Sopenharmony_ci    y = *x;
10457db96d56Sopenharmony_ci    return PyLong_FromLong(y);
10467db96d56Sopenharmony_ci
10477db96d56Sopenharmony_ci}
10487db96d56Sopenharmony_ci
10497db96d56Sopenharmony_cistatic void
10507db96d56Sopenharmony_cifaulthandler_raise_sigsegv(void)
10517db96d56Sopenharmony_ci{
10527db96d56Sopenharmony_ci    faulthandler_suppress_crash_report();
10537db96d56Sopenharmony_ci#if defined(MS_WINDOWS)
10547db96d56Sopenharmony_ci    /* For SIGSEGV, faulthandler_fatal_error() restores the previous signal
10557db96d56Sopenharmony_ci       handler and then gives back the execution flow to the program (without
10567db96d56Sopenharmony_ci       explicitly calling the previous error handler). In a normal case, the
10577db96d56Sopenharmony_ci       SIGSEGV was raised by the kernel because of a fault, and so if the
10587db96d56Sopenharmony_ci       program retries to execute the same instruction, the fault will be
10597db96d56Sopenharmony_ci       raised again.
10607db96d56Sopenharmony_ci
10617db96d56Sopenharmony_ci       Here the fault is simulated by a fake SIGSEGV signal raised by the
10627db96d56Sopenharmony_ci       application. We have to raise SIGSEGV at lease twice: once for
10637db96d56Sopenharmony_ci       faulthandler_fatal_error(), and one more time for the previous signal
10647db96d56Sopenharmony_ci       handler. */
10657db96d56Sopenharmony_ci    while(1)
10667db96d56Sopenharmony_ci        raise(SIGSEGV);
10677db96d56Sopenharmony_ci#else
10687db96d56Sopenharmony_ci    raise(SIGSEGV);
10697db96d56Sopenharmony_ci#endif
10707db96d56Sopenharmony_ci}
10717db96d56Sopenharmony_ci
10727db96d56Sopenharmony_cistatic PyObject *
10737db96d56Sopenharmony_cifaulthandler_sigsegv(PyObject *self, PyObject *args)
10747db96d56Sopenharmony_ci{
10757db96d56Sopenharmony_ci    int release_gil = 0;
10767db96d56Sopenharmony_ci    if (!PyArg_ParseTuple(args, "|i:_sigsegv", &release_gil))
10777db96d56Sopenharmony_ci        return NULL;
10787db96d56Sopenharmony_ci
10797db96d56Sopenharmony_ci    if (release_gil) {
10807db96d56Sopenharmony_ci        Py_BEGIN_ALLOW_THREADS
10817db96d56Sopenharmony_ci        faulthandler_raise_sigsegv();
10827db96d56Sopenharmony_ci        Py_END_ALLOW_THREADS
10837db96d56Sopenharmony_ci    } else {
10847db96d56Sopenharmony_ci        faulthandler_raise_sigsegv();
10857db96d56Sopenharmony_ci    }
10867db96d56Sopenharmony_ci    Py_RETURN_NONE;
10877db96d56Sopenharmony_ci}
10887db96d56Sopenharmony_ci
10897db96d56Sopenharmony_cistatic void _Py_NO_RETURN
10907db96d56Sopenharmony_cifaulthandler_fatal_error_thread(void *plock)
10917db96d56Sopenharmony_ci{
10927db96d56Sopenharmony_ci    Py_FatalError("in new thread");
10937db96d56Sopenharmony_ci}
10947db96d56Sopenharmony_ci
10957db96d56Sopenharmony_cistatic PyObject *
10967db96d56Sopenharmony_cifaulthandler_fatal_error_c_thread(PyObject *self, PyObject *args)
10977db96d56Sopenharmony_ci{
10987db96d56Sopenharmony_ci    long thread;
10997db96d56Sopenharmony_ci    PyThread_type_lock lock;
11007db96d56Sopenharmony_ci
11017db96d56Sopenharmony_ci    faulthandler_suppress_crash_report();
11027db96d56Sopenharmony_ci
11037db96d56Sopenharmony_ci    lock = PyThread_allocate_lock();
11047db96d56Sopenharmony_ci    if (lock == NULL)
11057db96d56Sopenharmony_ci        return PyErr_NoMemory();
11067db96d56Sopenharmony_ci
11077db96d56Sopenharmony_ci    PyThread_acquire_lock(lock, WAIT_LOCK);
11087db96d56Sopenharmony_ci
11097db96d56Sopenharmony_ci    thread = PyThread_start_new_thread(faulthandler_fatal_error_thread, lock);
11107db96d56Sopenharmony_ci    if (thread == -1) {
11117db96d56Sopenharmony_ci        PyThread_free_lock(lock);
11127db96d56Sopenharmony_ci        PyErr_SetString(PyExc_RuntimeError, "unable to start the thread");
11137db96d56Sopenharmony_ci        return NULL;
11147db96d56Sopenharmony_ci    }
11157db96d56Sopenharmony_ci
11167db96d56Sopenharmony_ci    /* wait until the thread completes: it will never occur, since Py_FatalError()
11177db96d56Sopenharmony_ci       exits the process immediately. */
11187db96d56Sopenharmony_ci    PyThread_acquire_lock(lock, WAIT_LOCK);
11197db96d56Sopenharmony_ci    PyThread_release_lock(lock);
11207db96d56Sopenharmony_ci    PyThread_free_lock(lock);
11217db96d56Sopenharmony_ci
11227db96d56Sopenharmony_ci    Py_RETURN_NONE;
11237db96d56Sopenharmony_ci}
11247db96d56Sopenharmony_ci
11257db96d56Sopenharmony_cistatic PyObject* _Py_NO_SANITIZE_UNDEFINED
11267db96d56Sopenharmony_cifaulthandler_sigfpe(PyObject *self, PyObject *args)
11277db96d56Sopenharmony_ci{
11287db96d56Sopenharmony_ci    faulthandler_suppress_crash_report();
11297db96d56Sopenharmony_ci
11307db96d56Sopenharmony_ci    /* Do an integer division by zero: raise a SIGFPE on Intel CPU, but not on
11317db96d56Sopenharmony_ci       PowerPC. Use volatile to disable compile-time optimizations. */
11327db96d56Sopenharmony_ci    volatile int x = 1, y = 0, z;
11337db96d56Sopenharmony_ci    z = x / y;
11347db96d56Sopenharmony_ci
11357db96d56Sopenharmony_ci    /* If the division by zero didn't raise a SIGFPE (e.g. on PowerPC),
11367db96d56Sopenharmony_ci       raise it manually. */
11377db96d56Sopenharmony_ci    raise(SIGFPE);
11387db96d56Sopenharmony_ci
11397db96d56Sopenharmony_ci    /* This line is never reached, but we pretend to make something with z
11407db96d56Sopenharmony_ci       to silence a compiler warning. */
11417db96d56Sopenharmony_ci    return PyLong_FromLong(z);
11427db96d56Sopenharmony_ci}
11437db96d56Sopenharmony_ci
11447db96d56Sopenharmony_cistatic PyObject *
11457db96d56Sopenharmony_cifaulthandler_sigabrt(PyObject *self, PyObject *args)
11467db96d56Sopenharmony_ci{
11477db96d56Sopenharmony_ci    faulthandler_suppress_crash_report();
11487db96d56Sopenharmony_ci    abort();
11497db96d56Sopenharmony_ci    Py_RETURN_NONE;
11507db96d56Sopenharmony_ci}
11517db96d56Sopenharmony_ci
11527db96d56Sopenharmony_ci#if defined(FAULTHANDLER_USE_ALT_STACK)
11537db96d56Sopenharmony_ci#define FAULTHANDLER_STACK_OVERFLOW
11547db96d56Sopenharmony_ci
11557db96d56Sopenharmony_cistatic uintptr_t
11567db96d56Sopenharmony_cistack_overflow(uintptr_t min_sp, uintptr_t max_sp, size_t *depth)
11577db96d56Sopenharmony_ci{
11587db96d56Sopenharmony_ci    /* Allocate (at least) 4096 bytes on the stack at each call.
11597db96d56Sopenharmony_ci
11607db96d56Sopenharmony_ci       bpo-23654, bpo-38965: use volatile keyword to prevent tail call
11617db96d56Sopenharmony_ci       optimization. */
11627db96d56Sopenharmony_ci    volatile unsigned char buffer[4096];
11637db96d56Sopenharmony_ci    uintptr_t sp = (uintptr_t)&buffer;
11647db96d56Sopenharmony_ci    *depth += 1;
11657db96d56Sopenharmony_ci    if (sp < min_sp || max_sp < sp)
11667db96d56Sopenharmony_ci        return sp;
11677db96d56Sopenharmony_ci    buffer[0] = 1;
11687db96d56Sopenharmony_ci    buffer[4095] = 0;
11697db96d56Sopenharmony_ci    return stack_overflow(min_sp, max_sp, depth);
11707db96d56Sopenharmony_ci}
11717db96d56Sopenharmony_ci
11727db96d56Sopenharmony_cistatic PyObject *
11737db96d56Sopenharmony_cifaulthandler_stack_overflow(PyObject *self, PyObject *Py_UNUSED(ignored))
11747db96d56Sopenharmony_ci{
11757db96d56Sopenharmony_ci    size_t depth, size;
11767db96d56Sopenharmony_ci    uintptr_t sp = (uintptr_t)&depth;
11777db96d56Sopenharmony_ci    uintptr_t stop, lower_limit, upper_limit;
11787db96d56Sopenharmony_ci
11797db96d56Sopenharmony_ci    faulthandler_suppress_crash_report();
11807db96d56Sopenharmony_ci    depth = 0;
11817db96d56Sopenharmony_ci
11827db96d56Sopenharmony_ci    if (STACK_OVERFLOW_MAX_SIZE <= sp) {
11837db96d56Sopenharmony_ci        lower_limit = sp - STACK_OVERFLOW_MAX_SIZE;
11847db96d56Sopenharmony_ci    }
11857db96d56Sopenharmony_ci    else {
11867db96d56Sopenharmony_ci        lower_limit = 0;
11877db96d56Sopenharmony_ci    }
11887db96d56Sopenharmony_ci
11897db96d56Sopenharmony_ci    if (UINTPTR_MAX - STACK_OVERFLOW_MAX_SIZE >= sp) {
11907db96d56Sopenharmony_ci        upper_limit = sp + STACK_OVERFLOW_MAX_SIZE;
11917db96d56Sopenharmony_ci    }
11927db96d56Sopenharmony_ci    else {
11937db96d56Sopenharmony_ci        upper_limit = UINTPTR_MAX;
11947db96d56Sopenharmony_ci    }
11957db96d56Sopenharmony_ci
11967db96d56Sopenharmony_ci    stop = stack_overflow(lower_limit, upper_limit, &depth);
11977db96d56Sopenharmony_ci    if (sp < stop)
11987db96d56Sopenharmony_ci        size = stop - sp;
11997db96d56Sopenharmony_ci    else
12007db96d56Sopenharmony_ci        size = sp - stop;
12017db96d56Sopenharmony_ci    PyErr_Format(PyExc_RuntimeError,
12027db96d56Sopenharmony_ci        "unable to raise a stack overflow (allocated %zu bytes "
12037db96d56Sopenharmony_ci        "on the stack, %zu recursive calls)",
12047db96d56Sopenharmony_ci        size, depth);
12057db96d56Sopenharmony_ci    return NULL;
12067db96d56Sopenharmony_ci}
12077db96d56Sopenharmony_ci#endif   /* defined(FAULTHANDLER_USE_ALT_STACK) && defined(HAVE_SIGACTION) */
12087db96d56Sopenharmony_ci
12097db96d56Sopenharmony_ci
12107db96d56Sopenharmony_cistatic int
12117db96d56Sopenharmony_cifaulthandler_traverse(PyObject *module, visitproc visit, void *arg)
12127db96d56Sopenharmony_ci{
12137db96d56Sopenharmony_ci    Py_VISIT(thread.file);
12147db96d56Sopenharmony_ci#ifdef FAULTHANDLER_USER
12157db96d56Sopenharmony_ci    if (user_signals != NULL) {
12167db96d56Sopenharmony_ci        for (size_t signum=0; signum < Py_NSIG; signum++)
12177db96d56Sopenharmony_ci            Py_VISIT(user_signals[signum].file);
12187db96d56Sopenharmony_ci    }
12197db96d56Sopenharmony_ci#endif
12207db96d56Sopenharmony_ci    Py_VISIT(fatal_error.file);
12217db96d56Sopenharmony_ci    return 0;
12227db96d56Sopenharmony_ci}
12237db96d56Sopenharmony_ci
12247db96d56Sopenharmony_ci#ifdef MS_WINDOWS
12257db96d56Sopenharmony_cistatic PyObject *
12267db96d56Sopenharmony_cifaulthandler_raise_exception(PyObject *self, PyObject *args)
12277db96d56Sopenharmony_ci{
12287db96d56Sopenharmony_ci    unsigned int code, flags = 0;
12297db96d56Sopenharmony_ci    if (!PyArg_ParseTuple(args, "I|I:_raise_exception", &code, &flags))
12307db96d56Sopenharmony_ci        return NULL;
12317db96d56Sopenharmony_ci    faulthandler_suppress_crash_report();
12327db96d56Sopenharmony_ci    RaiseException(code, flags, 0, NULL);
12337db96d56Sopenharmony_ci    Py_RETURN_NONE;
12347db96d56Sopenharmony_ci}
12357db96d56Sopenharmony_ci#endif
12367db96d56Sopenharmony_ci
12377db96d56Sopenharmony_ciPyDoc_STRVAR(module_doc,
12387db96d56Sopenharmony_ci"faulthandler module.");
12397db96d56Sopenharmony_ci
12407db96d56Sopenharmony_cistatic PyMethodDef module_methods[] = {
12417db96d56Sopenharmony_ci    {"enable",
12427db96d56Sopenharmony_ci     _PyCFunction_CAST(faulthandler_py_enable), METH_VARARGS|METH_KEYWORDS,
12437db96d56Sopenharmony_ci     PyDoc_STR("enable(file=sys.stderr, all_threads=True): "
12447db96d56Sopenharmony_ci               "enable the fault handler")},
12457db96d56Sopenharmony_ci    {"disable", faulthandler_disable_py, METH_NOARGS,
12467db96d56Sopenharmony_ci     PyDoc_STR("disable(): disable the fault handler")},
12477db96d56Sopenharmony_ci    {"is_enabled", faulthandler_is_enabled, METH_NOARGS,
12487db96d56Sopenharmony_ci     PyDoc_STR("is_enabled()->bool: check if the handler is enabled")},
12497db96d56Sopenharmony_ci    {"dump_traceback",
12507db96d56Sopenharmony_ci     _PyCFunction_CAST(faulthandler_dump_traceback_py), METH_VARARGS|METH_KEYWORDS,
12517db96d56Sopenharmony_ci     PyDoc_STR("dump_traceback(file=sys.stderr, all_threads=True): "
12527db96d56Sopenharmony_ci               "dump the traceback of the current thread, or of all threads "
12537db96d56Sopenharmony_ci               "if all_threads is True, into file")},
12547db96d56Sopenharmony_ci    {"dump_traceback_later",
12557db96d56Sopenharmony_ci     _PyCFunction_CAST(faulthandler_dump_traceback_later), METH_VARARGS|METH_KEYWORDS,
12567db96d56Sopenharmony_ci     PyDoc_STR("dump_traceback_later(timeout, repeat=False, file=sys.stderrn, exit=False):\n"
12577db96d56Sopenharmony_ci               "dump the traceback of all threads in timeout seconds,\n"
12587db96d56Sopenharmony_ci               "or each timeout seconds if repeat is True. If exit is True, "
12597db96d56Sopenharmony_ci               "call _exit(1) which is not safe.")},
12607db96d56Sopenharmony_ci    {"cancel_dump_traceback_later",
12617db96d56Sopenharmony_ci     faulthandler_cancel_dump_traceback_later_py, METH_NOARGS,
12627db96d56Sopenharmony_ci     PyDoc_STR("cancel_dump_traceback_later():\ncancel the previous call "
12637db96d56Sopenharmony_ci               "to dump_traceback_later().")},
12647db96d56Sopenharmony_ci#ifdef FAULTHANDLER_USER
12657db96d56Sopenharmony_ci    {"register",
12667db96d56Sopenharmony_ci     _PyCFunction_CAST(faulthandler_register_py), METH_VARARGS|METH_KEYWORDS,
12677db96d56Sopenharmony_ci     PyDoc_STR("register(signum, file=sys.stderr, all_threads=True, chain=False): "
12687db96d56Sopenharmony_ci               "register a handler for the signal 'signum': dump the "
12697db96d56Sopenharmony_ci               "traceback of the current thread, or of all threads if "
12707db96d56Sopenharmony_ci               "all_threads is True, into file")},
12717db96d56Sopenharmony_ci    {"unregister",
12727db96d56Sopenharmony_ci     _PyCFunction_CAST(faulthandler_unregister_py), METH_VARARGS|METH_KEYWORDS,
12737db96d56Sopenharmony_ci     PyDoc_STR("unregister(signum): unregister the handler of the signal "
12747db96d56Sopenharmony_ci                "'signum' registered by register()")},
12757db96d56Sopenharmony_ci#endif
12767db96d56Sopenharmony_ci    {"_read_null", faulthandler_read_null, METH_NOARGS,
12777db96d56Sopenharmony_ci     PyDoc_STR("_read_null(): read from NULL, raise "
12787db96d56Sopenharmony_ci               "a SIGSEGV or SIGBUS signal depending on the platform")},
12797db96d56Sopenharmony_ci    {"_sigsegv", faulthandler_sigsegv, METH_VARARGS,
12807db96d56Sopenharmony_ci     PyDoc_STR("_sigsegv(release_gil=False): raise a SIGSEGV signal")},
12817db96d56Sopenharmony_ci    {"_fatal_error_c_thread", faulthandler_fatal_error_c_thread, METH_NOARGS,
12827db96d56Sopenharmony_ci     PyDoc_STR("fatal_error_c_thread(): "
12837db96d56Sopenharmony_ci               "call Py_FatalError() in a new C thread.")},
12847db96d56Sopenharmony_ci    {"_sigabrt", faulthandler_sigabrt, METH_NOARGS,
12857db96d56Sopenharmony_ci     PyDoc_STR("_sigabrt(): raise a SIGABRT signal")},
12867db96d56Sopenharmony_ci    {"_sigfpe", (PyCFunction)faulthandler_sigfpe, METH_NOARGS,
12877db96d56Sopenharmony_ci     PyDoc_STR("_sigfpe(): raise a SIGFPE signal")},
12887db96d56Sopenharmony_ci#ifdef FAULTHANDLER_STACK_OVERFLOW
12897db96d56Sopenharmony_ci    {"_stack_overflow", faulthandler_stack_overflow, METH_NOARGS,
12907db96d56Sopenharmony_ci     PyDoc_STR("_stack_overflow(): recursive call to raise a stack overflow")},
12917db96d56Sopenharmony_ci#endif
12927db96d56Sopenharmony_ci#ifdef MS_WINDOWS
12937db96d56Sopenharmony_ci    {"_raise_exception", faulthandler_raise_exception, METH_VARARGS,
12947db96d56Sopenharmony_ci     PyDoc_STR("raise_exception(code, flags=0): Call RaiseException(code, flags).")},
12957db96d56Sopenharmony_ci#endif
12967db96d56Sopenharmony_ci    {NULL, NULL}  /* sentinel */
12977db96d56Sopenharmony_ci};
12987db96d56Sopenharmony_ci
12997db96d56Sopenharmony_cistatic int
13007db96d56Sopenharmony_ciPyExec_faulthandler(PyObject *module) {
13017db96d56Sopenharmony_ci    /* Add constants for unit tests */
13027db96d56Sopenharmony_ci#ifdef MS_WINDOWS
13037db96d56Sopenharmony_ci    /* RaiseException() codes (prefixed by an underscore) */
13047db96d56Sopenharmony_ci    if (PyModule_AddIntConstant(module, "_EXCEPTION_ACCESS_VIOLATION",
13057db96d56Sopenharmony_ci                                EXCEPTION_ACCESS_VIOLATION)) {
13067db96d56Sopenharmony_ci        return -1;
13077db96d56Sopenharmony_ci    }
13087db96d56Sopenharmony_ci    if (PyModule_AddIntConstant(module, "_EXCEPTION_INT_DIVIDE_BY_ZERO",
13097db96d56Sopenharmony_ci                                EXCEPTION_INT_DIVIDE_BY_ZERO)) {
13107db96d56Sopenharmony_ci        return -1;
13117db96d56Sopenharmony_ci    }
13127db96d56Sopenharmony_ci    if (PyModule_AddIntConstant(module, "_EXCEPTION_STACK_OVERFLOW",
13137db96d56Sopenharmony_ci                                EXCEPTION_STACK_OVERFLOW)) {
13147db96d56Sopenharmony_ci        return -1;
13157db96d56Sopenharmony_ci    }
13167db96d56Sopenharmony_ci
13177db96d56Sopenharmony_ci    /* RaiseException() flags (prefixed by an underscore) */
13187db96d56Sopenharmony_ci    if (PyModule_AddIntConstant(module, "_EXCEPTION_NONCONTINUABLE",
13197db96d56Sopenharmony_ci                                EXCEPTION_NONCONTINUABLE)) {
13207db96d56Sopenharmony_ci        return -1;
13217db96d56Sopenharmony_ci    }
13227db96d56Sopenharmony_ci    if (PyModule_AddIntConstant(module, "_EXCEPTION_NONCONTINUABLE_EXCEPTION",
13237db96d56Sopenharmony_ci                                EXCEPTION_NONCONTINUABLE_EXCEPTION)) {
13247db96d56Sopenharmony_ci        return -1;
13257db96d56Sopenharmony_ci    }
13267db96d56Sopenharmony_ci#endif
13277db96d56Sopenharmony_ci    return 0;
13287db96d56Sopenharmony_ci}
13297db96d56Sopenharmony_ci
13307db96d56Sopenharmony_cistatic PyModuleDef_Slot faulthandler_slots[] = {
13317db96d56Sopenharmony_ci    {Py_mod_exec, PyExec_faulthandler},
13327db96d56Sopenharmony_ci    {0, NULL}
13337db96d56Sopenharmony_ci};
13347db96d56Sopenharmony_ci
13357db96d56Sopenharmony_cistatic struct PyModuleDef module_def = {
13367db96d56Sopenharmony_ci    PyModuleDef_HEAD_INIT,
13377db96d56Sopenharmony_ci    .m_name = "faulthandler",
13387db96d56Sopenharmony_ci    .m_doc = module_doc,
13397db96d56Sopenharmony_ci    .m_methods = module_methods,
13407db96d56Sopenharmony_ci    .m_traverse = faulthandler_traverse,
13417db96d56Sopenharmony_ci    .m_slots = faulthandler_slots
13427db96d56Sopenharmony_ci};
13437db96d56Sopenharmony_ci
13447db96d56Sopenharmony_ciPyMODINIT_FUNC
13457db96d56Sopenharmony_ciPyInit_faulthandler(void)
13467db96d56Sopenharmony_ci{
13477db96d56Sopenharmony_ci    return PyModuleDef_Init(&module_def);
13487db96d56Sopenharmony_ci}
13497db96d56Sopenharmony_ci
13507db96d56Sopenharmony_cistatic int
13517db96d56Sopenharmony_cifaulthandler_init_enable(void)
13527db96d56Sopenharmony_ci{
13537db96d56Sopenharmony_ci    PyObject *module = PyImport_ImportModule("faulthandler");
13547db96d56Sopenharmony_ci    if (module == NULL) {
13557db96d56Sopenharmony_ci        return -1;
13567db96d56Sopenharmony_ci    }
13577db96d56Sopenharmony_ci
13587db96d56Sopenharmony_ci    PyObject *res = PyObject_CallMethodNoArgs(module, &_Py_ID(enable));
13597db96d56Sopenharmony_ci    Py_DECREF(module);
13607db96d56Sopenharmony_ci    if (res == NULL) {
13617db96d56Sopenharmony_ci        return -1;
13627db96d56Sopenharmony_ci    }
13637db96d56Sopenharmony_ci    Py_DECREF(res);
13647db96d56Sopenharmony_ci
13657db96d56Sopenharmony_ci    return 0;
13667db96d56Sopenharmony_ci}
13677db96d56Sopenharmony_ci
13687db96d56Sopenharmony_ciPyStatus
13697db96d56Sopenharmony_ci_PyFaulthandler_Init(int enable)
13707db96d56Sopenharmony_ci{
13717db96d56Sopenharmony_ci#ifdef FAULTHANDLER_USE_ALT_STACK
13727db96d56Sopenharmony_ci    memset(&stack, 0, sizeof(stack));
13737db96d56Sopenharmony_ci    stack.ss_flags = 0;
13747db96d56Sopenharmony_ci    /* bpo-21131: allocate dedicated stack of SIGSTKSZ*2 bytes, instead of just
13757db96d56Sopenharmony_ci       SIGSTKSZ bytes. Calling the previous signal handler in faulthandler
13767db96d56Sopenharmony_ci       signal handler uses more than SIGSTKSZ bytes of stack memory on some
13777db96d56Sopenharmony_ci       platforms. */
13787db96d56Sopenharmony_ci    stack.ss_size = SIGSTKSZ * 2;
13797db96d56Sopenharmony_ci#ifdef AT_MINSIGSTKSZ
13807db96d56Sopenharmony_ci    /* bpo-46968: Query Linux for minimal stack size to ensure signal delivery
13817db96d56Sopenharmony_ci       for the hardware running CPython. This OS feature is available in
13827db96d56Sopenharmony_ci       Linux kernel version >= 5.14 */
13837db96d56Sopenharmony_ci    unsigned long at_minstack_size = getauxval(AT_MINSIGSTKSZ);
13847db96d56Sopenharmony_ci    if (at_minstack_size != 0) {
13857db96d56Sopenharmony_ci        stack.ss_size = SIGSTKSZ + at_minstack_size;
13867db96d56Sopenharmony_ci    }
13877db96d56Sopenharmony_ci#endif
13887db96d56Sopenharmony_ci#endif
13897db96d56Sopenharmony_ci
13907db96d56Sopenharmony_ci    memset(&thread, 0, sizeof(thread));
13917db96d56Sopenharmony_ci
13927db96d56Sopenharmony_ci    if (enable) {
13937db96d56Sopenharmony_ci        if (faulthandler_init_enable() < 0) {
13947db96d56Sopenharmony_ci            return _PyStatus_ERR("failed to enable faulthandler");
13957db96d56Sopenharmony_ci        }
13967db96d56Sopenharmony_ci    }
13977db96d56Sopenharmony_ci    return _PyStatus_OK();
13987db96d56Sopenharmony_ci}
13997db96d56Sopenharmony_ci
14007db96d56Sopenharmony_civoid _PyFaulthandler_Fini(void)
14017db96d56Sopenharmony_ci{
14027db96d56Sopenharmony_ci    /* later */
14037db96d56Sopenharmony_ci    if (thread.cancel_event) {
14047db96d56Sopenharmony_ci        cancel_dump_traceback_later();
14057db96d56Sopenharmony_ci        PyThread_release_lock(thread.cancel_event);
14067db96d56Sopenharmony_ci        PyThread_free_lock(thread.cancel_event);
14077db96d56Sopenharmony_ci        thread.cancel_event = NULL;
14087db96d56Sopenharmony_ci    }
14097db96d56Sopenharmony_ci    if (thread.running) {
14107db96d56Sopenharmony_ci        PyThread_free_lock(thread.running);
14117db96d56Sopenharmony_ci        thread.running = NULL;
14127db96d56Sopenharmony_ci    }
14137db96d56Sopenharmony_ci
14147db96d56Sopenharmony_ci#ifdef FAULTHANDLER_USER
14157db96d56Sopenharmony_ci    /* user */
14167db96d56Sopenharmony_ci    if (user_signals != NULL) {
14177db96d56Sopenharmony_ci        for (size_t signum=0; signum < Py_NSIG; signum++) {
14187db96d56Sopenharmony_ci            faulthandler_unregister(&user_signals[signum], signum);
14197db96d56Sopenharmony_ci        }
14207db96d56Sopenharmony_ci        PyMem_Free(user_signals);
14217db96d56Sopenharmony_ci        user_signals = NULL;
14227db96d56Sopenharmony_ci    }
14237db96d56Sopenharmony_ci#endif
14247db96d56Sopenharmony_ci
14257db96d56Sopenharmony_ci    /* fatal */
14267db96d56Sopenharmony_ci    faulthandler_disable();
14277db96d56Sopenharmony_ci
14287db96d56Sopenharmony_ci#ifdef FAULTHANDLER_USE_ALT_STACK
14297db96d56Sopenharmony_ci    if (stack.ss_sp != NULL) {
14307db96d56Sopenharmony_ci        /* Fetch the current alt stack */
14317db96d56Sopenharmony_ci        stack_t current_stack;
14327db96d56Sopenharmony_ci        memset(&current_stack, 0, sizeof(current_stack));
14337db96d56Sopenharmony_ci        if (sigaltstack(NULL, &current_stack) == 0) {
14347db96d56Sopenharmony_ci            if (current_stack.ss_sp == stack.ss_sp) {
14357db96d56Sopenharmony_ci                /* The current alt stack is the one that we installed.
14367db96d56Sopenharmony_ci                 It is safe to restore the old stack that we found when
14377db96d56Sopenharmony_ci                 we installed ours */
14387db96d56Sopenharmony_ci                sigaltstack(&old_stack, NULL);
14397db96d56Sopenharmony_ci            } else {
14407db96d56Sopenharmony_ci                /* Someone switched to a different alt stack and didn't
14417db96d56Sopenharmony_ci                   restore ours when they were done (if they're done).
14427db96d56Sopenharmony_ci                   There's not much we can do in this unlikely case */
14437db96d56Sopenharmony_ci            }
14447db96d56Sopenharmony_ci        }
14457db96d56Sopenharmony_ci        PyMem_Free(stack.ss_sp);
14467db96d56Sopenharmony_ci        stack.ss_sp = NULL;
14477db96d56Sopenharmony_ci    }
14487db96d56Sopenharmony_ci#endif
14497db96d56Sopenharmony_ci}
1450