[Python-checkins] gh-81057: Move faulthandler Globals to _PyRuntimeState (gh-100152)

ericsnowcurrently webhook-mailer at python.org
Mon Dec 12 11:59:26 EST 2022


https://github.com/python/cpython/commit/53d9cd95cd91f1a291a3923acb95e0e86942291a
commit: 53d9cd95cd91f1a291a3923acb95e0e86942291a
branch: main
author: Eric Snow <ericsnowcurrently at gmail.com>
committer: ericsnowcurrently <ericsnowcurrently at gmail.com>
date: 2022-12-12T09:58:46-07:00
summary:

gh-81057: Move faulthandler Globals to _PyRuntimeState (gh-100152)

https://github.com/python/cpython/issues/81057

files:
A Include/internal/pycore_faulthandler.h
M Include/internal/pycore_runtime.h
M Include/internal/pycore_runtime_init.h
M Makefile.pre.in
M Modules/faulthandler.c
M PCbuild/pythoncore.vcxproj
M PCbuild/pythoncore.vcxproj.filters
M Tools/c-analyzer/cpython/globals-to-fix.tsv
M Tools/c-analyzer/cpython/ignored.tsv

diff --git a/Include/internal/pycore_faulthandler.h b/Include/internal/pycore_faulthandler.h
new file mode 100644
index 000000000000..e6aec7745a64
--- /dev/null
+++ b/Include/internal/pycore_faulthandler.h
@@ -0,0 +1,99 @@
+#ifndef Py_INTERNAL_FAULTHANDLER_H
+#define Py_INTERNAL_FAULTHANDLER_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef Py_BUILD_CORE
+#  error "this header requires Py_BUILD_CORE define"
+#endif
+
+#ifdef HAVE_SIGACTION
+#  include <signal.h>
+#endif
+
+
+#ifndef MS_WINDOWS
+   /* register() is useless on Windows, because only SIGSEGV, SIGABRT and
+      SIGILL can be handled by the process, and these signals can only be used
+      with enable(), not using register() */
+#  define FAULTHANDLER_USER
+#endif
+
+
+#ifdef HAVE_SIGACTION
+/* Using an alternative stack requires sigaltstack()
+   and sigaction() SA_ONSTACK */
+#  ifdef HAVE_SIGALTSTACK
+#    define FAULTHANDLER_USE_ALT_STACK
+#  endif
+typedef struct sigaction _Py_sighandler_t;
+#else
+typedef PyOS_sighandler_t _Py_sighandler_t;
+#endif  // HAVE_SIGACTION
+
+
+#ifdef FAULTHANDLER_USER
+struct faulthandler_user_signal {
+    int enabled;
+    PyObject *file;
+    int fd;
+    int all_threads;
+    int chain;
+    _Py_sighandler_t previous;
+    PyInterpreterState *interp;
+};
+#endif /* FAULTHANDLER_USER */
+
+
+struct _faulthandler_runtime_state {
+    struct {
+        int enabled;
+        PyObject *file;
+        int fd;
+        int all_threads;
+        PyInterpreterState *interp;
+#ifdef MS_WINDOWS
+        void *exc_handler;
+#endif
+    } fatal_error;
+
+    struct {
+        PyObject *file;
+        int fd;
+        PY_TIMEOUT_T timeout_us;   /* timeout in microseconds */
+        int repeat;
+        PyInterpreterState *interp;
+        int exit;
+        char *header;
+        size_t header_len;
+        /* The main thread always holds this lock. It is only released when
+           faulthandler_thread() is interrupted before this thread exits, or at
+           Python exit. */
+        PyThread_type_lock cancel_event;
+        /* released by child thread when joined */
+        PyThread_type_lock running;
+    } thread;
+
+#ifdef FAULTHANDLER_USER
+    struct faulthandler_user_signal *user_signals;
+#endif
+
+#ifdef FAULTHANDLER_USE_ALT_STACK
+    stack_t stack;
+    stack_t old_stack;
+#endif
+};
+
+#define _faulthandler_runtime_state_INIT \
+    { \
+        .fatal_error = { \
+            .fd = -1, \
+        }, \
+    }
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_INTERNAL_FAULTHANDLER_H */
diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h
index 99ec6fc8862b..b9ed8f593156 100644
--- a/Include/internal/pycore_runtime.h
+++ b/Include/internal/pycore_runtime.h
@@ -13,6 +13,7 @@ extern "C" {
 #include "pycore_dict_state.h"      // struct _Py_dict_runtime_state
 #include "pycore_dtoa.h"            // struct _dtoa_runtime_state
 #include "pycore_floatobject.h"     // struct _Py_float_runtime_state
+#include "pycore_faulthandler.h"    // struct _faulthandler_runtime_state
 #include "pycore_function.h"        // struct _func_runtime_state
 #include "pycore_global_objects.h"  // struct _Py_global_objects
 #include "pycore_import.h"          // struct _import_runtime_state
@@ -140,6 +141,7 @@ typedef struct pyruntimestate {
     struct _getargs_runtime_state getargs;
     struct _dtoa_runtime_state dtoa;
     struct _fileutils_state fileutils;
+    struct _faulthandler_runtime_state faulthandler;
     struct _tracemalloc_runtime_state tracemalloc;
 
     PyPreConfig preconfig;
diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h
index 029357dedf3e..9677a727c446 100644
--- a/Include/internal/pycore_runtime_init.h
+++ b/Include/internal/pycore_runtime_init.h
@@ -54,6 +54,7 @@ extern "C" {
         .fileutils = { \
             .force_ascii = -1, \
         }, \
+        .faulthandler = _faulthandler_runtime_state_INIT, \
         .tracemalloc = _tracemalloc_runtime_state_INIT, \
         .float_state = { \
             .float_format = _py_float_format_unknown, \
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 9577f9dee6da..dd6c3fbd1c64 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -1634,6 +1634,7 @@ PYTHON_HEADERS= \
 		$(srcdir)/Include/internal/pycore_descrobject.h \
 		$(srcdir)/Include/internal/pycore_dtoa.h \
 		$(srcdir)/Include/internal/pycore_exceptions.h \
+		$(srcdir)/Include/internal/pycore_faulthandler.h \
 		$(srcdir)/Include/internal/pycore_fileutils.h \
 		$(srcdir)/Include/internal/pycore_floatobject.h \
 		$(srcdir)/Include/internal/pycore_format.h \
diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
index 341a03a244cd..5309a3728c5e 100644
--- a/Modules/faulthandler.c
+++ b/Modules/faulthandler.c
@@ -18,12 +18,6 @@
 #  include <sys/resource.h>
 #endif
 
-/* Using an alternative stack requires sigaltstack()
-   and sigaction() SA_ONSTACK */
-#if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)
-#  define FAULTHANDLER_USE_ALT_STACK
-#endif
-
 #if defined(FAULTHANDLER_USE_ALT_STACK) && defined(HAVE_LINUX_AUXVEC_H) && defined(HAVE_SYS_AUXV_H)
 #  include <linux/auxvec.h>       // AT_MINSIGSTKSZ
 #  include <sys/auxv.h>           // getauxval()
@@ -32,13 +26,6 @@
 /* Allocate at maximum 100 MiB of the stack to raise the stack overflow */
 #define STACK_OVERFLOW_MAX_SIZE (100 * 1024 * 1024)
 
-#ifndef MS_WINDOWS
-   /* register() is useless on Windows, because only SIGSEGV, SIGABRT and
-      SIGILL can be handled by the process, and these signals can only be used
-      with enable(), not using register() */
-#  define FAULTHANDLER_USER
-#endif
-
 #define PUTS(fd, str) _Py_write_noraise(fd, str, strlen(str))
 
 
@@ -58,12 +45,6 @@
 #endif
 
 
-#ifdef HAVE_SIGACTION
-typedef struct sigaction _Py_sighandler_t;
-#else
-typedef PyOS_sighandler_t _Py_sighandler_t;
-#endif
-
 typedef struct {
     int signum;
     int enabled;
@@ -72,47 +53,12 @@ typedef struct {
     int all_threads;
 } fault_handler_t;
 
-static struct {
-    int enabled;
-    PyObject *file;
-    int fd;
-    int all_threads;
-    PyInterpreterState *interp;
-#ifdef MS_WINDOWS
-    void *exc_handler;
-#endif
-} fatal_error = {0, NULL, -1, 0};
-
-static struct {
-    PyObject *file;
-    int fd;
-    PY_TIMEOUT_T timeout_us;   /* timeout in microseconds */
-    int repeat;
-    PyInterpreterState *interp;
-    int exit;
-    char *header;
-    size_t header_len;
-    /* The main thread always holds this lock. It is only released when
-       faulthandler_thread() is interrupted before this thread exits, or at
-       Python exit. */
-    PyThread_type_lock cancel_event;
-    /* released by child thread when joined */
-    PyThread_type_lock running;
-} thread;
+#define fatal_error _PyRuntime.faulthandler.fatal_error
+#define thread _PyRuntime.faulthandler.thread
 
 #ifdef FAULTHANDLER_USER
-typedef struct {
-    int enabled;
-    PyObject *file;
-    int fd;
-    int all_threads;
-    int chain;
-    _Py_sighandler_t previous;
-    PyInterpreterState *interp;
-} user_signal_t;
-
-static user_signal_t *user_signals;
-
+#define user_signals _PyRuntime.faulthandler.user_signals
+typedef struct faulthandler_user_signal user_signal_t;
 static void faulthandler_user(int signum);
 #endif /* FAULTHANDLER_USER */
 
@@ -134,8 +80,8 @@ static const size_t faulthandler_nsignals = \
     Py_ARRAY_LENGTH(faulthandler_handlers);
 
 #ifdef FAULTHANDLER_USE_ALT_STACK
-static stack_t stack;
-static stack_t old_stack;
+#  define stack _PyRuntime.faulthandler.stack
+#  define old_stack _PyRuntime.faulthandler.old_stack
 #endif
 
 
@@ -1094,7 +1040,7 @@ faulthandler_fatal_error_thread(void *plock)
 static PyObject *
 faulthandler_fatal_error_c_thread(PyObject *self, PyObject *args)
 {
-    long thread;
+    long tid;
     PyThread_type_lock lock;
 
     faulthandler_suppress_crash_report();
@@ -1105,8 +1051,8 @@ faulthandler_fatal_error_c_thread(PyObject *self, PyObject *args)
 
     PyThread_acquire_lock(lock, WAIT_LOCK);
 
-    thread = PyThread_start_new_thread(faulthandler_fatal_error_thread, lock);
-    if (thread == -1) {
+    tid = PyThread_start_new_thread(faulthandler_fatal_error_thread, lock);
+    if (tid == -1) {
         PyThread_free_lock(lock);
         PyErr_SetString(PyExc_RuntimeError, "unable to start the thread");
         return NULL;
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index 25572d6ebcd5..bb2aaae3317b 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -214,6 +214,7 @@
     <ClInclude Include="..\Include\internal\pycore_dict_state.h" />
     <ClInclude Include="..\Include\internal\pycore_dtoa.h" />
     <ClInclude Include="..\Include\internal\pycore_exceptions.h" />
+    <ClInclude Include="..\Include\internal\pycore_faulthandler.h" />
     <ClInclude Include="..\Include\internal\pycore_fileutils.h" />
     <ClInclude Include="..\Include\internal\pycore_floatobject.h" />
     <ClInclude Include="..\Include\internal\pycore_format.h" />
diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters
index d45b50c5d62d..339e7cc4937a 100644
--- a/PCbuild/pythoncore.vcxproj.filters
+++ b/PCbuild/pythoncore.vcxproj.filters
@@ -549,6 +549,9 @@
     <ClInclude Include="..\Include\internal\pycore_exceptions.h">
       <Filter>Include\internal</Filter>
     </ClInclude>
+    <ClInclude Include="..\Include\internal\pycore_faulthandler.h">
+      <Filter>Include\internal</Filter>
+    </ClInclude>
     <ClInclude Include="..\Include\internal\pycore_fileutils.h">
       <Filter>Include\internal</Filter>
     </ClInclude>
@@ -558,6 +561,9 @@
     <ClInclude Include="..\Include\internal\pycore_format.h">
       <Filter>Include\internal</Filter>
     </ClInclude>
+    <ClInclude Include="..\Include\internal\pycore_function.h">
+      <Filter>Include\internal</Filter>
+    </ClInclude>
     <ClInclude Include="..\Include\internal\pycore_gc.h">
       <Filter>Include\internal</Filter>
     </ClInclude>
diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv
index 5dcd396c5487..eb57f95abd17 100644
--- a/Tools/c-analyzer/cpython/globals-to-fix.tsv
+++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv
@@ -361,15 +361,6 @@ Modules/itertoolsmodule.c	-	tee_type	-
 Modules/itertoolsmodule.c	-	teedataobject_type	-
 Modules/itertoolsmodule.c	-	ziplongest_type	-
 
-##-----------------------
-## state
-
-Modules/faulthandler.c	-	fatal_error	-
-Modules/faulthandler.c	-	thread	-
-Modules/faulthandler.c	-	user_signals	-
-Modules/faulthandler.c	-	stack	-
-Modules/faulthandler.c	-	old_stack	-
-
 
 ##################################
 ## global non-objects to fix in builtin modules
@@ -377,7 +368,6 @@ Modules/faulthandler.c	-	old_stack	-
 ##-----------------------
 ## state
 
-Modules/faulthandler.c	faulthandler_dump_traceback	reentrant	-
 Modules/signalmodule.c	-	is_tripped	-
 Modules/signalmodule.c	-	signal_global_state	-
 Modules/signalmodule.c	-	wakeup	-
diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv
index 7d6ff0ba6d64..b03198627f42 100644
--- a/Tools/c-analyzer/cpython/ignored.tsv
+++ b/Tools/c-analyzer/cpython/ignored.tsv
@@ -151,6 +151,7 @@ Python/sysmodule.c	-	_preinit_xoptions	-
 
 # thread-safety
 # XXX need race protection?
+Modules/faulthandler.c	faulthandler_dump_traceback	reentrant	-
 Python/pylifecycle.c	_Py_FatalErrorFormat	reentrant	-
 Python/pylifecycle.c	fatal_error	reentrant	-
 



More information about the Python-checkins mailing list