Skip to content

Commit

Permalink
pythongh-76785: Improved Subinterpreters Compatibility with 3.12 (2/2) (
Browse files Browse the repository at this point in the history
pythongh-126707)

These changes makes it easier to backport the _interpreters, _interpqueues, and _interpchannels modules to Python 3.12.

This involves the following:

* add the _PyXI_GET_STATE() and _PyXI_GET_GLOBAL_STATE() macros
* add _PyXIData_lookup_context_t and _PyXIData_GetLookupContext()
* add _Py_xi_state_init() and _Py_xi_state_fini()
  • Loading branch information
ericsnowcurrently authored and ebonnal committed Jan 10, 2025
1 parent f12dc2a commit 37b4768
Show file tree
Hide file tree
Showing 9 changed files with 247 additions and 91 deletions.
33 changes: 29 additions & 4 deletions Include/internal/pycore_crossinterp.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,26 @@ typedef int (*xidatafunc)(PyThreadState *tstate, PyObject *, _PyXIData_t *);

typedef struct _xid_lookup_state _PyXIData_lookup_t;

PyAPI_FUNC(xidatafunc) _PyXIData_Lookup(PyObject *);
PyAPI_FUNC(int) _PyObject_CheckXIData(PyObject *);
PyAPI_FUNC(int) _PyObject_GetXIData(PyObject *, _PyXIData_t *);
typedef struct {
_PyXIData_lookup_t *global;
_PyXIData_lookup_t *local;
PyObject *PyExc_NotShareableError;
} _PyXIData_lookup_context_t;

PyAPI_FUNC(int) _PyXIData_GetLookupContext(
PyInterpreterState *,
_PyXIData_lookup_context_t *);

PyAPI_FUNC(xidatafunc) _PyXIData_Lookup(
_PyXIData_lookup_context_t *,
PyObject *);
PyAPI_FUNC(int) _PyObject_CheckXIData(
_PyXIData_lookup_context_t *,
PyObject *);
PyAPI_FUNC(int) _PyObject_GetXIData(
_PyXIData_lookup_context_t *,
PyObject *,
_PyXIData_t *);


/* using cross-interpreter data */
Expand Down Expand Up @@ -173,12 +190,20 @@ typedef struct {
} exceptions;
} _PyXI_state_t;

#define _PyXI_GET_GLOBAL_STATE(interp) (&(interp)->runtime->xi)
#define _PyXI_GET_STATE(interp) (&(interp)->xi)

#ifndef Py_BUILD_CORE_MODULE
extern PyStatus _PyXI_Init(PyInterpreterState *interp);
extern void _PyXI_Fini(PyInterpreterState *interp);
extern PyStatus _PyXI_InitTypes(PyInterpreterState *interp);
extern void _PyXI_FiniTypes(PyInterpreterState *interp);
#endif // Py_BUILD_CORE_MODULE

#define _PyInterpreterState_GetXIState(interp) (&(interp)->xi)
int _Py_xi_global_state_init(_PyXI_global_state_t *);
void _Py_xi_global_state_fini(_PyXI_global_state_t *);
int _Py_xi_state_init(_PyXI_state_t *, PyInterpreterState *);
void _Py_xi_state_fini(_PyXI_state_t *, PyInterpreterState *);


/***************************/
Expand Down
9 changes: 7 additions & 2 deletions Include/internal/pycore_crossinterp_data_registry.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,13 @@ typedef struct {
_PyXIData_regitem_t *head;
} _PyXIData_registry_t;

PyAPI_FUNC(int) _PyXIData_RegisterClass(PyTypeObject *, xidatafunc);
PyAPI_FUNC(int) _PyXIData_UnregisterClass(PyTypeObject *);
PyAPI_FUNC(int) _PyXIData_RegisterClass(
_PyXIData_lookup_context_t *,
PyTypeObject *,
xidatafunc);
PyAPI_FUNC(int) _PyXIData_UnregisterClass(
_PyXIData_lookup_context_t *,
PyTypeObject *);

struct _xid_lookup_state {
// XXX Remove this field once we have a tp_* slot.
Expand Down
7 changes: 6 additions & 1 deletion Modules/_interpchannelsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1758,6 +1758,11 @@ channel_send(_channels *channels, int64_t cid, PyObject *obj,
}
int64_t interpid = PyInterpreterState_GetID(interp);

_PyXIData_lookup_context_t ctx;
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
return -1;
}

// Look up the channel.
PyThread_type_lock mutex = NULL;
_channel_state *chan = NULL;
Expand All @@ -1779,7 +1784,7 @@ channel_send(_channels *channels, int64_t cid, PyObject *obj,
PyThread_release_lock(mutex);
return -1;
}
if (_PyObject_GetXIData(obj, data) != 0) {
if (_PyObject_GetXIData(&ctx, obj, data) != 0) {
PyThread_release_lock(mutex);
GLOBAL_FREE(data);
return -1;
Expand Down
11 changes: 8 additions & 3 deletions Modules/_interpqueuesmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,12 @@ queue_destroy(_queues *queues, int64_t qid)
static int
queue_put(_queues *queues, int64_t qid, PyObject *obj, int fmt, int unboundop)
{
PyInterpreterState *interp = PyInterpreterState_Get();
_PyXIData_lookup_context_t ctx;
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
return -1;
}

// Look up the queue.
_queue *queue = NULL;
int err = _queues_lookup(queues, qid, &queue);
Expand All @@ -1141,13 +1147,12 @@ queue_put(_queues *queues, int64_t qid, PyObject *obj, int fmt, int unboundop)
_queue_unmark_waiter(queue, queues->mutex);
return -1;
}
if (_PyObject_GetXIData(obj, data) != 0) {
if (_PyObject_GetXIData(&ctx, obj, data) != 0) {
_queue_unmark_waiter(queue, queues->mutex);
GLOBAL_FREE(data);
return -1;
}
assert(_PyXIData_INTERPID(data) == \
PyInterpreterState_GetID(PyInterpreterState_Get()));
assert(_PyXIData_INTERPID(data) == PyInterpreterState_GetID(interp));

// Add the data to the queue.
int64_t interpid = -1; // _queueitem_init() will set it.
Expand Down
15 changes: 12 additions & 3 deletions Modules/_interpreters_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,24 @@
static int
ensure_xid_class(PyTypeObject *cls, xidatafunc getdata)
{
//assert(cls->tp_flags & Py_TPFLAGS_HEAPTYPE);
return _PyXIData_RegisterClass(cls, getdata);
PyInterpreterState *interp = PyInterpreterState_Get();
_PyXIData_lookup_context_t ctx;
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
return -1;
}
return _PyXIData_RegisterClass(&ctx, cls, getdata);
}

#ifdef REGISTERS_HEAP_TYPES
static int
clear_xid_class(PyTypeObject *cls)
{
return _PyXIData_UnregisterClass(cls);
PyInterpreterState *interp = PyInterpreterState_Get();
_PyXIData_lookup_context_t ctx;
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
return -1;
}
return _PyXIData_UnregisterClass(&ctx, cls);
}
#endif

Expand Down
17 changes: 13 additions & 4 deletions Modules/_interpretersmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1186,7 +1186,13 @@ object_is_shareable(PyObject *self, PyObject *args, PyObject *kwds)
return NULL;
}

if (_PyObject_CheckXIData(obj) == 0) {
PyInterpreterState *interp = PyInterpreterState_Get();
_PyXIData_lookup_context_t ctx;
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
return NULL;
}

if (_PyObject_CheckXIData(&ctx, obj) == 0) {
Py_RETURN_TRUE;
}
PyErr_Clear();
Expand Down Expand Up @@ -1485,6 +1491,11 @@ module_exec(PyObject *mod)
PyInterpreterState *interp = PyInterpreterState_Get();
module_state *state = get_module_state(mod);

_PyXIData_lookup_context_t ctx;
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
return -1;
}

#define ADD_WHENCE(NAME) \
if (PyModule_AddIntConstant(mod, "WHENCE_" #NAME, \
_PyInterpreterState_WHENCE_##NAME) < 0) \
Expand All @@ -1506,9 +1517,7 @@ module_exec(PyObject *mod)
if (PyModule_AddType(mod, (PyTypeObject *)PyExc_InterpreterNotFoundError) < 0) {
goto error;
}
PyObject *PyExc_NotShareableError = \
_PyInterpreterState_GetXIState(interp)->exceptions.PyExc_NotShareableError;
if (PyModule_AddType(mod, (PyTypeObject *)PyExc_NotShareableError) < 0) {
if (PyModule_AddType(mod, (PyTypeObject *)ctx.PyExc_NotShareableError) < 0) {
goto error;
}

Expand Down
8 changes: 7 additions & 1 deletion Modules/_testinternalcapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1797,6 +1797,12 @@ _xid_capsule_destructor(PyObject *capsule)
static PyObject *
get_crossinterp_data(PyObject *self, PyObject *args)
{
PyInterpreterState *interp = PyInterpreterState_Get();
_PyXIData_lookup_context_t ctx;
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
return NULL;
}

PyObject *obj = NULL;
if (!PyArg_ParseTuple(args, "O:get_crossinterp_data", &obj)) {
return NULL;
Expand All @@ -1806,7 +1812,7 @@ get_crossinterp_data(PyObject *self, PyObject *args)
if (data == NULL) {
return NULL;
}
if (_PyObject_GetXIData(obj, data) != 0) {
if (_PyObject_GetXIData(&ctx, obj, data) != 0) {
_PyXIData_Free(data);
return NULL;
}
Expand Down
Loading

0 comments on commit 37b4768

Please sign in to comment.