summaryrefslogtreecommitdiffstats
path: root/Modules/_xxinterpchannelsmodule.c
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2023-09-19 21:01:34 (GMT)
committerGitHub <noreply@github.com>2023-09-19 21:01:34 (GMT)
commitfd7e08a6f35581e1189b9bf12feb51f7167a86c5 (patch)
tree0844ef241ff291d4d50d293e185532b1284b276b /Modules/_xxinterpchannelsmodule.c
parent754519a9f8c2bb06d85ff9b3e9fe6f967ac46d5c (diff)
downloadcpython-fd7e08a6f35581e1189b9bf12feb51f7167a86c5.zip
cpython-fd7e08a6f35581e1189b9bf12feb51f7167a86c5.tar.gz
cpython-fd7e08a6f35581e1189b9bf12feb51f7167a86c5.tar.bz2
gh-76785: Use Pending Calls When Releasing Cross-Interpreter Data (gh-109556)
This fixes some crashes in the _xxinterpchannels module, due to a race between interpreters.
Diffstat (limited to 'Modules/_xxinterpchannelsmodule.c')
-rw-r--r--Modules/_xxinterpchannelsmodule.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/Modules/_xxinterpchannelsmodule.c b/Modules/_xxinterpchannelsmodule.c
index 60ac8ed..6096f88 100644
--- a/Modules/_xxinterpchannelsmodule.c
+++ b/Modules/_xxinterpchannelsmodule.c
@@ -160,14 +160,24 @@ add_new_type(PyObject *mod, PyType_Spec *spec, crossinterpdatafunc shared)
return cls;
}
+#define XID_IGNORE_EXC 1
+#define XID_FREE 2
+
static int
-_release_xid_data(_PyCrossInterpreterData *data, int ignoreexc)
+_release_xid_data(_PyCrossInterpreterData *data, int flags)
{
+ int ignoreexc = flags & XID_IGNORE_EXC;
PyObject *exc;
if (ignoreexc) {
exc = PyErr_GetRaisedException();
}
- int res = _PyCrossInterpreterData_Release(data);
+ int res;
+ if (flags & XID_FREE) {
+ res = _PyCrossInterpreterData_ReleaseAndRawFree(data);
+ }
+ else {
+ res = _PyCrossInterpreterData_Release(data);
+ }
if (res < 0) {
/* The owning interpreter is already destroyed. */
if (ignoreexc) {
@@ -175,6 +185,9 @@ _release_xid_data(_PyCrossInterpreterData *data, int ignoreexc)
PyErr_Clear();
}
}
+ if (flags & XID_FREE) {
+ /* Either way, we free the data. */
+ }
if (ignoreexc) {
PyErr_SetRaisedException(exc);
}
@@ -366,9 +379,8 @@ static void
_channelitem_clear(_channelitem *item)
{
if (item->data != NULL) {
- (void)_release_xid_data(item->data, 1);
// It was allocated in _channel_send().
- GLOBAL_FREE(item->data);
+ (void)_release_xid_data(item->data, XID_IGNORE_EXC & XID_FREE);
item->data = NULL;
}
item->next = NULL;
@@ -1439,14 +1451,12 @@ _channel_recv(_channels *channels, int64_t id, PyObject **res)
PyObject *obj = _PyCrossInterpreterData_NewObject(data);
if (obj == NULL) {
assert(PyErr_Occurred());
- (void)_release_xid_data(data, 1);
- // It was allocated in _channel_send().
- GLOBAL_FREE(data);
+ // It was allocated in _channel_send(), so we free it.
+ (void)_release_xid_data(data, XID_IGNORE_EXC | XID_FREE);
return -1;
}
- int release_res = _release_xid_data(data, 0);
- // It was allocated in _channel_send().
- GLOBAL_FREE(data);
+ // It was allocated in _channel_send(), so we free it.
+ int release_res = _release_xid_data(data, XID_FREE);
if (release_res < 0) {
// The source interpreter has been destroyed already.
assert(PyErr_Occurred());