diff options
Diffstat (limited to 'Modules/faulthandler.c')
| -rw-r--r-- | Modules/faulthandler.c | 97 |
1 files changed, 61 insertions, 36 deletions
diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 680f630..1493f8d 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -22,7 +22,14 @@ # define FAULTHANDLER_USER #endif -#define PUTS(fd, str) write(fd, str, strlen(str)) +/* cast size_t to int because write() takes an int on Windows + (anyway, the length is smaller than 30 characters) */ +#define PUTS(fd, str) write(fd, str, (int)strlen(str)) + +_Py_IDENTIFIER(enable); +_Py_IDENTIFIER(fileno); +_Py_IDENTIFIER(flush); +_Py_IDENTIFIER(stderr); #ifdef HAVE_SIGACTION typedef struct sigaction _Py_sighandler_t; @@ -79,9 +86,6 @@ typedef struct { static user_signal_t *user_signals; /* the following macros come from Python: Modules/signalmodule.c */ -#if defined(PYOS_OS2) && !defined(PYCC_GCC) -#define NSIG 12 -#endif #ifndef NSIG # if defined(_NSIG) # define NSIG _NSIG /* For BSD/SysV */ @@ -131,17 +135,19 @@ static PyObject* faulthandler_get_fileno(PyObject *file, int *p_fd) { PyObject *result; - _Py_IDENTIFIER(fileno); - _Py_IDENTIFIER(flush); long fd_long; int fd; if (file == NULL || file == Py_None) { - file = PySys_GetObject("stderr"); + file = _PySys_GetObjectId(&PyId_stderr); if (file == NULL) { PyErr_SetString(PyExc_RuntimeError, "unable to get sys.stderr"); return NULL; } + if (file == Py_None) { + PyErr_SetString(PyExc_RuntimeError, "sys.stderr is None"); + return NULL; + } } result = _PyObject_CallMethodId(file, &PyId_fileno, ""); @@ -448,7 +454,7 @@ faulthandler_thread(void *unused) /* get the thread holding the GIL, NULL if no thread hold the GIL */ current = _Py_atomic_load_relaxed(&_PyThreadState_Current); - write(thread.fd, thread.header, thread.header_len); + write(thread.fd, thread.header, (int)thread.header_len); errmsg = _Py_DumpTracebackThreads(thread.fd, thread.interp, current); ok = (errmsg == NULL); @@ -476,7 +482,7 @@ cancel_dump_traceback_later(void) Py_CLEAR(thread.file); if (thread.header) { - free(thread.header); + PyMem_Free(thread.header); thread.header = NULL; } } @@ -505,7 +511,7 @@ format_timeout(double timeout) "Timeout (%lu:%02lu:%02lu)!\n", hour, min, sec); - return strdup(buffer); + return _PyMem_Strdup(buffer); } static PyObject* @@ -571,7 +577,7 @@ faulthandler_dump_traceback_later(PyObject *self, if (PyThread_start_new_thread(faulthandler_thread, NULL) == -1) { PyThread_release_lock(thread.running); Py_CLEAR(thread.file); - free(header); + PyMem_Free(header); thread.header = NULL; PyErr_SetString(PyExc_RuntimeError, "unable to start watchdog thread"); @@ -730,9 +736,10 @@ faulthandler_register_py(PyObject *self, return NULL; if (user_signals == NULL) { - user_signals = calloc(NSIG, sizeof(user_signal_t)); + user_signals = PyMem_Malloc(NSIG * sizeof(user_signal_t)); if (user_signals == NULL) return PyErr_NoMemory(); + memset(user_signals, 0, NSIG * sizeof(user_signal_t)); } user = &user_signals[signum]; @@ -802,23 +809,15 @@ faulthandler_read_null(PyObject *self, PyObject *args) { volatile int *x; volatile int y; - int release_gil = 0; - if (!PyArg_ParseTuple(args, "|i:_read_null", &release_gil)) - return NULL; x = NULL; - if (release_gil) { - Py_BEGIN_ALLOW_THREADS - y = *x; - Py_END_ALLOW_THREADS - } else - y = *x; + y = *x; return PyLong_FromLong(y); } -static PyObject * -faulthandler_sigsegv(PyObject *self, PyObject *args) +static void +faulthandler_raise_sigsegv(void) { #if defined(MS_WINDOWS) /* For SIGSEGV, faulthandler_fatal_error() restores the previous signal @@ -837,6 +836,22 @@ faulthandler_sigsegv(PyObject *self, PyObject *args) #else raise(SIGSEGV); #endif +} + +static PyObject * +faulthandler_sigsegv(PyObject *self, PyObject *args) +{ + int release_gil = 0; + if (!PyArg_ParseTuple(args, "|i:_read_null", &release_gil)) + return NULL; + + if (release_gil) { + Py_BEGIN_ALLOW_THREADS + faulthandler_raise_sigsegv(); + Py_END_ALLOW_THREADS + } else { + faulthandler_raise_sigsegv(); + } Py_RETURN_NONE; } @@ -896,12 +911,19 @@ faulthandler_fatal_error_py(PyObject *self, PyObject *args) } #if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION) -static void* -stack_overflow(void *min_sp, void *max_sp, size_t *depth) +#ifdef __INTEL_COMPILER + /* Issue #23654: Turn off ICC's tail call optimization for the + * stack_overflow generator. ICC turns the recursive tail call into + * a loop. */ +# pragma intel optimization_level 0 +#endif +static +Py_uintptr_t +stack_overflow(Py_uintptr_t min_sp, Py_uintptr_t max_sp, size_t *depth) { /* allocate 4096 bytes on the stack at each call */ unsigned char buffer[4096]; - void *sp = &buffer; + Py_uintptr_t sp = (Py_uintptr_t)&buffer; *depth += 1; if (sp < min_sp || max_sp < sp) return sp; @@ -914,7 +936,8 @@ static PyObject * faulthandler_stack_overflow(PyObject *self) { size_t depth, size; - char *sp = (char *)&depth, *stop; + Py_uintptr_t sp = (Py_uintptr_t)&depth; + Py_uintptr_t stop; depth = 0; stop = stack_overflow(sp - STACK_OVERFLOW_MAX_SIZE, @@ -996,12 +1019,12 @@ static PyMethodDef module_methods[] = { "'signum' registered by register()")}, #endif - {"_read_null", faulthandler_read_null, METH_VARARGS, - PyDoc_STR("_read_null(release_gil=False): read from NULL, raise " + {"_read_null", faulthandler_read_null, METH_NOARGS, + PyDoc_STR("_read_null(): read from NULL, raise " "a SIGSEGV or SIGBUS signal depending on the platform")}, {"_sigsegv", faulthandler_sigsegv, METH_VARARGS, - PyDoc_STR("_sigsegv(): raise a SIGSEGV signal")}, - {"_sigabrt", faulthandler_sigabrt, METH_VARARGS, + PyDoc_STR("_sigsegv(release_gil=False): raise a SIGSEGV signal")}, + {"_sigabrt", faulthandler_sigabrt, METH_NOARGS, PyDoc_STR("_sigabrt(): raise a SIGABRT signal")}, {"_sigfpe", (PyCFunction)faulthandler_sigfpe, METH_NOARGS, PyDoc_STR("_sigfpe(): raise a SIGFPE signal")}, @@ -1047,9 +1070,11 @@ static int faulthandler_env_options(void) { PyObject *xoptions, *key, *module, *res; - _Py_IDENTIFIER(enable); + char *p; - if (!Py_GETENV("PYTHONFAULTHANDLER")) { + if (!((p = Py_GETENV("PYTHONFAULTHANDLER")) && *p != '\0')) { + /* PYTHONFAULTHANDLER environment variable is missing + or an empty string */ int has_key; xoptions = PySys_GetXOptions(); @@ -1062,8 +1087,8 @@ faulthandler_env_options(void) has_key = PyDict_Contains(xoptions, key); Py_DECREF(key); - if (!has_key) - return 0; + if (has_key <= 0) + return has_key; } module = PyImport_ImportModule("faulthandler"); @@ -1137,7 +1162,7 @@ void _PyFaulthandler_Fini(void) if (user_signals != NULL) { for (signum=0; signum < NSIG; signum++) faulthandler_unregister(&user_signals[signum], signum); - free(user_signals); + PyMem_Free(user_signals); user_signals = NULL; } #endif |
