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(¤t_stack, 0, sizeof(current_stack)); 14337db96d56Sopenharmony_ci if (sigaltstack(NULL, ¤t_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