8000 gh-76785: Minor Cleanup of Exception-related Cross-interpreter State by ericsnowcurrently · Pull Request #126602 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-76785: Minor Cleanup of Exception-related Cross-interpreter State #126602

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Add _PyXI_state_t.exceptions, init_static_exctypes(), fini_static_exc…
…types(), etc.
  • Loading branch information
ericsnowcurrently committed Nov 7, 2024
commit e5e0a6cc04a98a5f72f4d41d077442ef631b914c
10 changes: 8 additions & 2 deletions Include/internal/pycore_crossinterp.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ extern "C" {
#include "pycore_lock.h" // PyMutex
#include "pycore_pyerrors.h"


/**************/
/* exceptions */
/**************/
Expand Down Expand Up @@ -163,8 +164,13 @@ struct _xi_state {
// heap types
_PyXIData_lookup_t data_lookup;

// heap types
PyObject *PyExc_NotShareableError;
struct xi_exceptions {
// static types
PyObject *PyExc_InterpreterError;
PyObject *PyExc_InterpreterNotFoundError;
// heap types
PyObject *PyExc_NotShareableError;
} exceptions;
};

extern PyStatus _PyXI_Init(PyInterpreterState *interp);
Expand Down
2 changes: 1 addition & 1 deletion Modules/_interpretersmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1502,7 +1502,7 @@ module_exec(PyObject *mod)
goto error;
}
PyObject *PyExc_NotShareableError = \
_PyInterpreterState_GetXIState(interp)->PyExc_NotShareableError;
_PyInterpreterState_GetXIState(interp)->exceptions.PyExc_NotShareableError;
if (PyModule_AddType(mod, (PyTypeObject *)PyExc_NotShareableError) < 0) {
goto error;
}
Expand Down
35 changes: 21 additions & 14 deletions Python/crossinterp.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
/* exceptions */
/**************/

static int init_exceptions(PyInterpreterState *, int);
static void fini_exceptions(PyInterpreterState *, int);
static PyObject * _get_not_shareable_error_type(PyInterpreterState *);
typedef struct xi_exceptions exceptions_t;
static int init_static_exctypes(exceptions_t *, PyInterpreterState *);
static void fini_static_exctypes(exceptions_t *, PyInterpreterState *);
static int init_heap_exctypes(exceptions_t *);
static void fini_heap_exctypes(exceptions_t *);
#include "crossinterp_exceptions.h"


Expand Down Expand Up @@ -203,7 +205,8 @@ static inline void
_set_xid_lookup_failure(PyInterpreterState *interp,
PyObject *obj, const char *msg)
{
PyObject *exctype = _get_not_shareable_error_type(interp);
exceptions_t *state = &_PyInterpreterState_GetXIState(interp)->exceptions;
PyObject *exctype = state->PyExc_NotShareableError;
assert(exctype != NULL);
if (msg != NULL) {
assert(obj == NULL);
Expand Down Expand Up @@ -1603,7 +1606,9 @@ _propagate_not_shareable_error(_PyXI_session *session)
return;
}
PyInterpreterState *interp = PyInterpreterState_Get();
if (PyErr_ExceptionMatches(_get_not_shareable_error_type(interp))) {
exceptions_t *state = &_PyInterpreterState_GetXIState(interp)->exceptions;
assert(state->PyExc_NotShareableError != NULL);
if (PyErr_ExceptionMatches(state->PyExc_NotShareableError)) {
// We want to propagate the exception directly.
session->_error_override = _PyXI_ERR_NOT_SHAREABLE;
session->error_override = &session->_error_override;
Expand Down Expand Up @@ -1780,10 +1785,9 @@ _PyXI_Init(PyInterpreterState *interp)
}
xid_lookup_init(&_PyXI_GET_STATE(interp)->data_lookup);

// Initialize exceptions (heap types).
// We would initialize static types here too but that leads to ref leaks.
// Instead, we do it in _PyXI_InitTypes().
if (init_exceptions(interp, 0) < 0) {
// Initialize exceptions.(heap types).
// See _PyXI_InitTypes() for the static types.
if (init_heap_exctypes(&_PyXI_GET_STATE(interp)->exceptions) < 0) {
PyErr_PrintEx(0);
return _PyStatus_ERR("failed to initialize exceptions");
}
Expand All @@ -1798,9 +1802,8 @@ void
_PyXI_Fini(PyInterpreterState *interp)
{
8000 // Finalize exceptions (heap types).
// We would finalize static types here too but that leads to ref leaks.
// Instead, we do it in _PyXI_FiniTypes().
fini_exceptions(interp, 0);
// See _PyXI_FiniTypes() for the static types.
fini_heap_exctypes(&_PyXI_GET_STATE(interp)->exceptions);

// Finalize the XID lookup state (e.g. registry).
xid_lookup_fini(&_PyXI_GET_STATE(interp)->data_lookup);
Expand All @@ -1812,17 +1815,21 @@ _PyXI_Fini(PyInterpreterState *interp)
PyStatus
_PyXI_InitTypes(PyInterpreterState *interp)
{
if (init_exceptions(interp, 1) < 0) {
if (init_static_exctypes(&_PyXI_GET_STATE(interp)->exceptions, interp) < 0) {
PyErr_PrintEx(0);
return _PyStatus_ERR("failed to initialize an exception type");
}
// We would initialize heap types here too but that leads to ref leaks.
// Instead, we intialize them in _PyXI_Init().
return _PyStatus_OK();
}

void
_PyXI_FiniTypes(PyInterpreterState *interp)
{
fini_exceptions(interp, 1);
// We would finalize heap types here too but that leads to ref leaks.
// Instead, we finalize them in _PyXI_Fini().
fini_static_exctypes(&_PyXI_GET_STATE(interp)->exceptions, interp);
}


Expand Down
117 changes: 53 additions & 64 deletions Python/crossinterp_exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,89 +25,78 @@ static PyTypeObject _PyExc_InterpreterNotFoundError = {
};
PyObject *PyExc_InterpreterNotFoundError = (PyObject *)&_PyExc_InterpreterNotFoundError;

static PyObject *
_get_not_shareable_error_type(PyInterpreterState *interp)
{
assert(_PyInterpreterState_GetXIState(interp)->PyExc_NotShareableError != NULL);
return _PyInterpreterState_GetXIState(interp)->PyExc_NotShareableError;
}


/* lifecycle */

static int
init_exceptions(PyInterpreterState *interp, int statictypes)
init_static_exctypes(exceptions_t *state, PyInterpreterState *interp)
{
int heaptypes = (!statictypes);

// Initialize static types.
int base_initialized = 0;
int notfound_initialized = 0;
if (statictypes) {
PyTypeObject *base = (PyTypeObject *)PyExc_Exception;

_PyExc_InterpreterError.tp_base = base;
_PyExc_InterpreterError.tp_traverse = base->tp_traverse;
_PyExc_InterpreterError.tp_clear = base->tp_clear;
if (_PyStaticType_InitBuiltin(interp, &_PyExc_InterpreterError) < 0) {
goto error;
}
base_initialized = 1;

_PyExc_InterpreterNotFoundError.tp_traverse = base->tp_traverse;
_PyExc_InterpreterNotFoundError.tp_clear = base->tp_clear;
if (_PyStaticType_InitBuiltin(interp, &_PyExc_InterpreterNotFoundError) < 0) {
goto error;
}
notfound_initialized = 1;
assert(state == &_PyXI_GET_STATE(interp)->exceptions);
PyTypeObject *base = (PyTypeObject *)PyExc_Exception;

// PyExc_InterpreterError
_PyExc_InterpreterError.tp_base = base;
_PyExc_InterpreterError.tp_traverse = base->tp_traverse;
_PyExc_InterpreterError.tp_clear = base->tp_clear;
if (_PyStaticType_InitBuiltin(interp, &_PyExc_InterpreterError) < 0) {
goto error;
}
state->PyExc_InterpreterError = (PyObject *)&_PyExc_InterpreterError;

// Initialize heap types.
if (heaptypes) {
/* NotShareableError extends ValueError */
const char *name = "interpreters.NotShareableError";
PyObject *base = PyExc_ValueError;
PyObject *ns = NULL;
PyObject *exctype = PyErr_NewException(name, base, ns);
if (exctype == NULL) {
goto error;
}
_PyInterpreterState_GetXIState(interp)->PyExc_NotShareableError = exctype;
// PyExc_InterpreterNotFoundError
_PyExc_InterpreterNotFoundError.tp_traverse = base->tp_traverse;
_PyExc_InterpreterNotFoundError.tp_clear = base->tp_clear;
if (_PyStaticType_InitBuiltin(interp, &_PyExc_InterpreterNotFoundError) < 0) {
goto error;
}

// Initialize heap types.

// We would call _init_not_shareable_error_type() here too,
// but that leads to ref leaks
state->PyExc_InterpreterNotFoundError =
(PyObject *)&_PyExc_InterpreterNotFoundError;

return 0;

error:
if (heaptypes) {
Py_CLEAR(_PyInterpreterState_GetXIState(interp)->PyExc_NotShareableError);
}
if (notfound_initialized) {
fini_static_exctypes(state, interp);
return -1;
}

static void
fini_static_exctypes(exceptions_t *state, PyInterpreterState *interp)
{
assert(state == &_PyXI_GET_STATE(interp)->exceptions);
if (state->PyExc_InterpreterNotFoundError != NULL) {
state->PyExc_InterpreterNotFoundError = NULL;
_PyStaticType_FiniBuiltin(interp, &_PyExc_InterpreterNotFoundError);
}
if (base_initialized) {
if (state->PyExc_InterpreterError != NULL) {
state->PyExc_InterpreterError = NULL;
_PyStaticType_FiniBuiltin(interp, &_PyExc_InterpreterError);
}
return -1;
}

static void
fini_exceptions(PyInterpreterState *interp, int statictypes)
static int
init_heap_exctypes(exceptions_t *state)
{
int heaptypes = (!statictypes);

// Finalize heap types.
if (heaptypes) {
Py_CLEAR(_PyInterpreterState_GetXIState(interp)->PyExc_NotShareableError);
PyObject *exctype;

/* NotShareableError extends ValueError */
const char *name = "interpreters.NotShareableError";
PyObject *base = PyExc_ValueError;
PyObject *ns = NULL;
exctype = PyErr_NewException(name, base, ns);
if (exctype == NULL) {
goto error;
}
state->PyExc_NotShareableError = exctype;

// Finalize static types.
if (statictypes) {
_PyStaticType_FiniBuiltin(interp, &_PyExc_InterpreterNotFoundError);
_PyStaticType_FiniBuiltin(interp, &_PyExc_InterpreterError);
}
return 0;

error:
fini_heap_exctypes(state);
return -1;
}

static void
fini_heap_exctypes(exceptions_t *state)
{
Py_CLEAR(state->PyExc_NotShareableError);
}
Loading
0