Skip to content

Commit

Permalink
gh-81057: Move faulthandler Globals to _PyRuntimeState (gh-100152)
Browse files Browse the repository at this point in the history
  • Loading branch information
ericsnowcurrently authored Dec 12, 2022
1 parent 8790d4d commit 53d9cd9
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 73 deletions.
99 changes: 99 additions & 0 deletions Include/internal/pycore_faulthandler.h
Original file line number Diff line number Diff line change
@@ -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 */
2 changes: 2 additions & 0 deletions Include/internal/pycore_runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions Include/internal/pycore_runtime_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -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, \
Expand Down
1 change: 1 addition & 0 deletions Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
72 changes: 9 additions & 63 deletions Modules/faulthandler.c
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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))


Expand All @@ -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;
Expand All @@ -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 */

Expand All @@ -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


Expand Down Expand Up @@ -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();
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions PCbuild/pythoncore.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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" />
Expand Down
6 changes: 6 additions & 0 deletions PCbuild/pythoncore.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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>
Expand Down
10 changes: 0 additions & 10 deletions Tools/c-analyzer/cpython/globals-to-fix.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -361,23 +361,13 @@ 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

##-----------------------
## state

Modules/faulthandler.c faulthandler_dump_traceback reentrant -
Modules/signalmodule.c - is_tripped -
Modules/signalmodule.c - signal_global_state -
Modules/signalmodule.c - wakeup -
Expand Down
1 change: 1 addition & 0 deletions Tools/c-analyzer/cpython/ignored.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -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 -

Expand Down

0 comments on commit 53d9cd9

Please sign in to comment.