summaryrefslogtreecommitdiffstats
path: root/Modules/faulthandler.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/faulthandler.c')
-rw-r--r--Modules/faulthandler.c97
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