8000 gh-99741: Clean Up the _xxsubinterpreters Module by ericsnowcurrently · Pull Request #99940 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-99741: Clean Up the _xxsubinterpreters Module #99940

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
Next Next commit
Return an error code from _PyCrossInterpreterData_Release().
  • Loading branch information
ericsnowcurrently committed Dec 2, 2022
commit 4f9baf0a4d56c1e166c31e01147e1ce595580b13
2 changes: 1 addition & 1 deletion Include/cpython/pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ struct _xid {

PyAPI_FUNC(int) _PyObject_GetCrossInterpreterData(PyObject *, _PyCrossInterpreterData *);
PyAPI_FUNC(PyObject *) _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *);
PyAPI_FUNC(void) _PyCrossInterpreterData_Release(_PyCrossInterpreterData *);
PyAPI_FUNC(int) _PyCrossInterpreterData_Release(_PyCrossInterpreterData *);

PyAPI_FUNC(int) _PyObject_CheckCrossInterpreterData(PyObject *);

Expand Down
13 changes: 13 additions & 0 deletions Lib/test/test__xxsubinterpreters.py
Original file line number Diff line number Diff line change
Expand Up @@ -1545,6 +1545,19 @@ def test_recv_default(self):
self.assertEqual(obj5, b'eggs')
self.assertIs(obj6, default)

def test_recv_sending_interp_destroyed(self):
cid = interpreters.channel_create()
interp = interpreters.create()
interpreters.run_string(interp, dedent(f"""
import _xxsubinterpreters as _interpreters
_interpreters.channel_send({cid}, b'spam')
"""))
interpreters.destroy(interp)

with self.assertRaisesRegex(RuntimeError,
'unrecognized interpreter ID'):
interpreters.channel_recv(cid)

def test_run_string_arg_unresolved(self):
cid = interpreters.channel_create()
interp = interpreters.create()
Expand Down
7 changes: 3 additions & 4 deletions Modules/_xxsubinterpretersmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,8 @@ _release_xid_data(_PyCrossInterpreterData *data, int ignoreexc)
if (ignoreexc) {
PyErr_Fetch(&exctype, &excval, &exctb);
}
int res = 0;
_PyCrossInterpreterData_Release(data);
if (PyErr_Occurred()) {
int res = _PyCrossInterpreterData_Release(data);
if (res < 0) {
// XXX Fix this!
/* The owning interpreter is already destroyed.
* Ideally, this shouldn't ever happen. When an interpreter is
Expand All @@ -128,7 +127,6 @@ _release_xid_data(_PyCrossInterpreterData *data, int ignoreexc)
// XXX Emit a warning?
PyErr_Clear();
}
res = 1;
}
if (ignoreexc) {
PyErr_Restore(exctype, excval, exctb);
Expand Down Expand Up @@ -1512,6 +1510,7 @@ _channel_recv(_channels *channels, int64_t id, PyObject **res)
return err;
}
else if (data == NULL) {
assert(!PyErr_Occurred());
return 0;
}

Expand Down
20 changes: 11 additions & 9 deletions Python/pystate.c
Original file line number Diff line number Diff line change
8000 Expand Up @@ -1865,7 +1865,7 @@ _PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data)
// Fill in the blanks and validate the result.
data->interp = interp->id;
if (_check_xidata(tstate, data) != 0) {
_PyCrossInterpreterData_Release(data);
(void)_PyCrossInterpreterData_Release(data);
return -1;
}

Expand All @@ -1878,8 +1878,8 @@ _release_xidata(void *arg)
_PyCrossInterpreterData *data = (_PyCrossInterpreterData *)arg;
if (data->free != NULL) {
data->free(data->data);
data->data = NULL;
}
data->data = NULL;
Py_CLEAR(data->obj);
}

Expand Down Expand Up @@ -1910,27 +1910,29 @@ _call_in_interpreter(struct _gilstate_runtime_state *gilstate,
}
}

void
int
_PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)
{
if (data->data == NULL && data->obj == NULL) {
if (data->free == NULL && data->obj == NULL) {
// Nothing to release!
return;
data->data = NULL;
return 0;
}

// Switch to the original interpreter.
PyInterpreterState *interp = _PyInterpreterState_LookUpID(data->interp);
if (interp == NULL) {
// The interpreter was already destroyed.
if (data->free != NULL) {
// XXX Someone leaked some memory...
}
return;
// This function shouldn't have been called.
// XXX Someone leaked some memory...
assert(PyErr_Occurred());
return -1;
}

// "Release" the data and/or the object.
struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate;
_call_in_interpreter(gilstate, interp, _release_xidata, data);
return 0;
}

PyObject *
Expand Down
0