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

https://github.com/python/cpython/issues/81057
This commit is contained in:
Eric Snow 2022-12-12 09:58:46 -07:00 committed by GitHub
parent 8790d4d31f
commit 53d9cd95cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 120 additions and 73 deletions

View File

@ -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 */

View File

@ -13,6 +13,7 @@ extern "C" {
#include "pycore_dict_state.h" // struct _Py_dict_runtime_state #include "pycore_dict_state.h" // struct _Py_dict_runtime_state
#include "pycore_dtoa.h" // struct _dtoa_runtime_state #include "pycore_dtoa.h" // struct _dtoa_runtime_state
#include "pycore_floatobject.h" // struct _Py_float_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_function.h" // struct _func_runtime_state
#include "pycore_global_objects.h" // struct _Py_global_objects #include "pycore_global_objects.h" // struct _Py_global_objects
#include "pycore_import.h" // struct _import_runtime_state #include "pycore_import.h" // struct _import_runtime_state
@ -140,6 +141,7 @@ typedef struct pyruntimestate {
struct _getargs_runtime_state getargs; struct _getargs_runtime_state getargs;
struct _dtoa_runtime_state dtoa; struct _dtoa_runtime_state dtoa;
struct _fileutils_state fileutils; struct _fileutils_state fileutils;
struct _faulthandler_runtime_state faulthandler;
struct _tracemalloc_runtime_state tracemalloc; struct _tracemalloc_runtime_state tracemalloc;
PyPreConfig preconfig; PyPreConfig preconfig;

View File

@ -54,6 +54,7 @@ extern "C" {
.fileutils = { \ .fileutils = { \
.force_ascii = -1, \ .force_ascii = -1, \
}, \ }, \
.faulthandler = _faulthandler_runtime_state_INIT, \
.tracemalloc = _tracemalloc_runtime_state_INIT, \ .tracemalloc = _tracemalloc_runtime_state_INIT, \
.float_state = { \ .float_state = { \
.float_format = _py_float_format_unknown, \ .float_format = _py_float_format_unknown, \

View File

@ -1634,6 +1634,7 @@ PYTHON_HEADERS= \
$(srcdir)/Include/internal/pycore_descrobject.h \ $(srcdir)/Include/internal/pycore_descrobject.h \
$(srcdir)/Include/internal/pycore_dtoa.h \ $(srcdir)/Include/internal/pycore_dtoa.h \
$(srcdir)/Include/internal/pycore_exceptions.h \ $(srcdir)/Include/internal/pycore_exceptions.h \
$(srcdir)/Include/internal/pycore_faulthandler.h \
$(srcdir)/Include/internal/pycore_fileutils.h \ $(srcdir)/Include/internal/pycore_fileutils.h \
$(srcdir)/Include/internal/pycore_floatobject.h \ $(srcdir)/Include/internal/pycore_floatobject.h \
$(srcdir)/Include/internal/pycore_format.h \ $(srcdir)/Include/internal/pycore_format.h \

View File

@ -18,12 +18,6 @@
# include <sys/resource.h> # include <sys/resource.h>
#endif #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) #if defined(FAULTHANDLER_USE_ALT_STACK) && defined(HAVE_LINUX_AUXVEC_H) && defined(HAVE_SYS_AUXV_H)
# include <linux/auxvec.h> // AT_MINSIGSTKSZ # include <linux/auxvec.h> // AT_MINSIGSTKSZ
# include <sys/auxv.h> // getauxval() # include <sys/auxv.h> // getauxval()
@ -32,13 +26,6 @@
/* Allocate at maximum 100 MiB of the stack to raise the stack overflow */ /* Allocate at maximum 100 MiB of the stack to raise the stack overflow */
#define STACK_OVERFLOW_MAX_SIZE (100 * 1024 * 1024) #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)) #define PUTS(fd, str) _Py_write_noraise(fd, str, strlen(str))
@ -58,12 +45,6 @@
#endif #endif
#ifdef HAVE_SIGACTION
typedef struct sigaction _Py_sighandler_t;
#else
typedef PyOS_sighandler_t _Py_sighandler_t;
#endif
typedef struct { typedef struct {
int signum; int signum;
int enabled; int enabled;
@ -72,47 +53,12 @@ typedef struct {
int all_threads; int all_threads;
} fault_handler_t; } fault_handler_t;
static struct { #define fatal_error _PyRuntime.faulthandler.fatal_error
int enabled; #define thread _PyRuntime.faulthandler.thread
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;
#ifdef FAULTHANDLER_USER #ifdef FAULTHANDLER_USER
typedef struct { #define user_signals _PyRuntime.faulthandler.user_signals
int enabled; typedef struct faulthandler_user_signal user_signal_t;
PyObject *file;
int fd;
int all_threads;
int chain;
_Py_sighandler_t previous;
PyInterpreterState *interp;
} user_signal_t;
static user_signal_t *user_signals;
static void faulthandler_user(int signum); static void faulthandler_user(int signum);
#endif /* FAULTHANDLER_USER */ #endif /* FAULTHANDLER_USER */
@ -134,8 +80,8 @@ static const size_t faulthandler_nsignals = \
Py_ARRAY_LENGTH(faulthandler_handlers); Py_ARRAY_LENGTH(faulthandler_handlers);
#ifdef FAULTHANDLER_USE_ALT_STACK #ifdef FAULTHANDLER_USE_ALT_STACK
static stack_t stack; # define stack _PyRuntime.faulthandler.stack
static stack_t old_stack; # define old_stack _PyRuntime.faulthandler.old_stack
#endif #endif
@ -1094,7 +1040,7 @@ faulthandler_fatal_error_thread(void *plock)
static PyObject * static PyObject *
faulthandler_fatal_error_c_thread(PyObject *self, PyObject *args) faulthandler_fatal_error_c_thread(PyObject *self, PyObject *args)
{ {
long thread; long tid;
PyThread_type_lock lock; PyThread_type_lock lock;
faulthandler_suppress_crash_report(); faulthandler_suppress_crash_report();
@ -1105,8 +1051,8 @@ faulthandler_fatal_error_c_thread(PyObject *self, PyObject *args)
PyThread_acquire_lock(lock, WAIT_LOCK); PyThread_acquire_lock(lock, WAIT_LOCK);
thread = PyThread_start_new_thread(faulthandler_fatal_error_thread, lock); tid = PyThread_start_new_thread(faulthandler_fatal_error_thread, lock);
if (thread == -1) { if (tid == -1) {
PyThread_free_lock(lock); PyThread_free_lock(lock);
PyErr_SetString(PyExc_RuntimeError, "unable to start the thread"); PyErr_SetString(PyExc_RuntimeError, "unable to start the thread");
return NULL; return NULL;

View File

@ -214,6 +214,7 @@
<ClInclude Include="..\Include\internal\pycore_dict_state.h" /> <ClInclude Include="..\Include\internal\pycore_dict_state.h" />
<ClInclude Include="..\Include\internal\pycore_dtoa.h" /> <ClInclude Include="..\Include\internal\pycore_dtoa.h" />
<ClInclude Include="..\Include\internal\pycore_exceptions.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_fileutils.h" />
<ClInclude Include="..\Include\internal\pycore_floatobject.h" /> <ClInclude Include="..\Include\internal\pycore_floatobject.h" />
<ClInclude Include="..\Include\internal\pycore_format.h" /> <ClInclude Include="..\Include\internal\pycore_format.h" />

View File

@ -549,6 +549,9 @@
<ClInclude Include="..\Include\internal\pycore_exceptions.h"> <ClInclude Include="..\Include\internal\pycore_exceptions.h">
<Filter>Include\internal</Filter> <Filter>Include\internal</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\Include\internal\pycore_faulthandler.h">
<Filter>Include\internal</Filter>
</ClInclude>
<ClInclude Include="..\Include\internal\pycore_fileutils.h"> <ClInclude Include="..\Include\internal\pycore_fileutils.h">
<Filter>Include\internal</Filter> <Filter>Include\internal</Filter>
</ClInclude> </ClInclude>
@ -558,6 +561,9 @@
<ClInclude Include="..\Include\internal\pycore_format.h"> <ClInclude Include="..\Include\internal\pycore_format.h">
<Filter>Include\internal</Filter> <Filter>Include\internal</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\Include\internal\pycore_function.h">
<Filter>Include\internal</Filter>
</ClInclude>
<ClInclude Include="..\Include\internal\pycore_gc.h"> <ClInclude Include="..\Include\internal\pycore_gc.h">
<Filter>Include\internal</Filter> <Filter>Include\internal</Filter>
</ClInclude> </ClInclude>

View File

@ -361,15 +361,6 @@ Modules/itertoolsmodule.c - tee_type -
Modules/itertoolsmodule.c - teedataobject_type - Modules/itertoolsmodule.c - teedataobject_type -
Modules/itertoolsmodule.c - ziplongest_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 ## global non-objects to fix in builtin modules
@ -377,7 +368,6 @@ Modules/faulthandler.c - old_stack -
##----------------------- ##-----------------------
## state ## state
Modules/faulthandler.c faulthandler_dump_traceback reentrant -
Modules/signalmodule.c - is_tripped - Modules/signalmodule.c - is_tripped -
Modules/signalmodule.c - signal_global_state - Modules/signalmodule.c - signal_global_state -
Modules/signalmodule.c - wakeup - Modules/signalmodule.c - wakeup -

Can't render this file because it has a wrong number of fields in line 4.

View File

@ -151,6 +151,7 @@ Python/sysmodule.c - _preinit_xoptions -
# thread-safety # thread-safety
# XXX need race protection? # XXX need race protection?
Modules/faulthandler.c faulthandler_dump_traceback reentrant -
Python/pylifecycle.c _Py_FatalErrorFormat reentrant - Python/pylifecycle.c _Py_FatalErrorFormat reentrant -
Python/pylifecycle.c fatal_error reentrant - Python/pylifecycle.c fatal_error reentrant -

Can't render this file because it has a wrong number of fields in line 4.