summaryrefslogtreecommitdiffstats
path: root/Python/pystate.c
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2018-06-02 00:45:20 (GMT)
committerGitHub <noreply@github.com>2018-06-02 00:45:20 (GMT)
commit63799136e6c0491bb5d6f4a234d5a775db3458db (patch)
tree73b6425dbddf05b042b2c48f9053232348fd3e0f /Python/pystate.c
parent29996a1c4e8bd6dde6adce2b44d11a0982a47a3a (diff)
downloadcpython-63799136e6c0491bb5d6f4a234d5a775db3458db.zip
cpython-63799136e6c0491bb5d6f4a234d5a775db3458db.tar.gz
cpython-63799136e6c0491bb5d6f4a234d5a775db3458db.tar.bz2
bpo-33615: Re-enable a subinterpreter test. (gh-7251)
For bpo-32604 I added extra subinterpreter-related tests (see #6914), which caused a few buildbots to crash. This patch fixes the crash by ensuring that refcounts in channels are handled properly.
Diffstat (limited to 'Python/pystate.c')
-rw-r--r--Python/pystate.c55
1 files changed, 37 insertions, 18 deletions
diff --git a/Python/pystate.c b/Python/pystate.c
index 4534c47..629598e 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -1205,7 +1205,6 @@ _PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data)
}
// Fill in the blanks and validate the result.
- Py_XINCREF(data->obj);
data->interp = interp->id;
if (_check_xidata(data) != 0) {
_PyCrossInterpreterData_Release(data);
@@ -1215,6 +1214,40 @@ _PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data)
return 0;
}
+static void
+_release_xidata(void *arg)
+{
+ _PyCrossInterpreterData *data = (_PyCrossInterpreterData *)arg;
+ if (data->free != NULL) {
+ data->free(data->data);
+ }
+ Py_XDECREF(data->obj);
+}
+
+static void
+_call_in_interpreter(PyInterpreterState *interp,
+ void (*func)(void *), void *arg)
+{
+ /* We would use Py_AddPendingCall() if it weren't specific to the
+ * main interpreter (see bpo-33608). In the meantime we take a
+ * naive approach.
+ */
+ PyThreadState *save_tstate = NULL;
+ if (interp != PyThreadState_Get()->interp) {
+ // XXX Using the "head" thread isn't strictly correct.
+ PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
+ // XXX Possible GILState issues?
+ save_tstate = PyThreadState_Swap(tstate);
+ }
+
+ func(arg);
+
+ // Switch back.
+ if (save_tstate != NULL) {
+ PyThreadState_Swap(save_tstate);
+ }
+}
+
void
_PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)
{
@@ -1233,24 +1266,8 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)
return;
}
- PyThreadState *save_tstate = NULL;
- if (interp != PyThreadState_Get()->interp) {
- // XXX Using the "head" thread isn't strictly correct.
- PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
- // XXX Possible GILState issues?
- save_tstate = PyThreadState_Swap(tstate);
- }
-
// "Release" the data and/or the object.
- if (data->free != NULL) {
- data->free(data->data);
- }
- Py_XDECREF(data->obj);
-
- // Switch back.
- if (save_tstate != NULL) {
- PyThreadState_Swap(save_tstate);
- }
+ _call_in_interpreter(interp, _release_xidata, data);
}
PyObject *
@@ -1355,6 +1372,7 @@ _bytes_shared(PyObject *obj, _PyCrossInterpreterData *data)
return -1;
}
data->data = (void *)shared;
+ Py_INCREF(obj);
data->obj = obj; // Will be "released" (decref'ed) when data released.
data->new_object = _new_bytes_object;
data->free = PyMem_Free;
@@ -1382,6 +1400,7 @@ _str_shared(PyObject *obj, _PyCrossInterpreterData *data)
shared->buffer = PyUnicode_DATA(obj);
shared->len = PyUnicode_GET_LENGTH(obj) - 1;
data->data = (void *)shared;
+ Py_INCREF(obj);
data->obj = obj; // Will be "released" (decref'ed) when data released.
data->new_object = _new_str_object;
data->free = PyMem_Free;