diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2023-10-04 00:36:50 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-04 00:36:50 (GMT) |
commit | 269005e78429d6ee518643daa633e9aa7e8b9c33 (patch) | |
tree | 7e2ee89bca5a30b844ca3b64a411b2c1fe22cef7 | |
parent | 625ecbe92eb69d2850c2e6dbe9538e9b1a098baa (diff) | |
download | cpython-269005e78429d6ee518643daa633e9aa7e8b9c33.zip cpython-269005e78429d6ee518643daa633e9aa7e8b9c33.tar.gz cpython-269005e78429d6ee518643daa633e9aa7e8b9c33.tar.bz2 |
gh-110300: Fix Refleaks in test_interpreters and test__xxinterpchannels (gh-110318)
-rw-r--r-- | Lib/test/support/interpreters.py | 3 | ||||
-rw-r--r-- | Lib/test/test_interpreters.py | 26 | ||||
-rw-r--r-- | Modules/_xxinterpchannelsmodule.c | 11 |
3 files changed, 30 insertions, 10 deletions
diff --git a/Lib/test/support/interpreters.py b/Lib/test/support/interpreters.py index d2beba3..3b50161 100644 --- a/Lib/test/support/interpreters.py +++ b/Lib/test/support/interpreters.py @@ -215,4 +215,5 @@ class SendChannel(_ChannelEnd): _channels.close(self._id, send=True) -_channels._register_end_types(SendChannel, RecvChannel) +# XXX This is causing leaks (gh-110318): +#_channels._register_end_types(SendChannel, RecvChannel) diff --git a/Lib/test/test_interpreters.py b/Lib/test/test_interpreters.py index ffdd8a1..f2ef172 100644 --- a/Lib/test/test_interpreters.py +++ b/Lib/test/test_interpreters.py @@ -68,6 +68,17 @@ def _running(interp): class TestBase(unittest.TestCase): + def pipe(self): + def ensure_closed(fd): + try: + os.close(fd) + except OSError: + pass + r, w = os.pipe() + self.addCleanup(lambda: ensure_closed(r)) + self.addCleanup(lambda: ensure_closed(w)) + return r, w + def tearDown(self): clean_up_interpreters() @@ -262,7 +273,7 @@ class TestInterpreterIsRunning(TestBase): self.assertFalse(interp.is_running()) def test_finished(self): - r, w = os.pipe() + r, w = self.pipe() interp = interpreters.create() interp.run(f"""if True: import os @@ -299,8 +310,8 @@ class TestInterpreterIsRunning(TestBase): interp.is_running() def test_with_only_background_threads(self): - r_interp, w_interp = os.pipe() - r_thread, w_thread = os.pipe() + r_interp, w_interp = self.pipe() + r_thread, w_thread = self.pipe() DONE = b'D' FINISHED = b'F' @@ -425,8 +436,8 @@ class TestInterpreterClose(TestBase): self.assertTrue(interp.is_running()) def test_subthreads_still_running(self): - r_interp, w_interp = os.pipe() - r_thread, w_thread = os.pipe() + r_interp, w_interp = self.pipe() + r_thread, w_thread = self.pipe() FINISHED = b'F' @@ -532,8 +543,8 @@ class TestInterpreterRun(TestBase): interp.run(b'print("spam")') def test_with_background_threads_still_running(self): - r_interp, w_interp = os.pipe() - r_thread, w_thread = os.pipe() + r_interp, w_interp = self.pipe() + r_thread, w_thread = self.pipe() RAN = b'R' DONE = b'D' @@ -822,6 +833,7 @@ class TestChannels(TestBase): after = set(interpreters.list_all_channels()) self.assertEqual(after, created) + @unittest.expectedFailure # See gh-110318: def test_shareable(self): rch, sch = interpreters.create_channel() diff --git a/Modules/_xxinterpchannelsmodule.c b/Modules/_xxinterpchannelsmodule.c index d5be76f..d762f44 100644 --- a/Modules/_xxinterpchannelsmodule.c +++ b/Modules/_xxinterpchannelsmodule.c @@ -1992,6 +1992,7 @@ _get_current_channel_end_type(int end) return NULL; } } + Py_DECREF(highlevel); if (end == CHANNEL_SEND) { cls = state->send_channel_type; } @@ -2012,6 +2013,7 @@ _channel_end_from_xid(_PyCrossInterpreterData *data) } PyTypeObject *cls = _get_current_channel_end_type(cid->end); if (cls == NULL) { + Py_DECREF(cid); return NULL; } PyObject *obj = PyObject_CallOneArg((PyObject *)cls, (PyObject *)cid); @@ -2027,7 +2029,9 @@ _channel_end_shared(PyThreadState *tstate, PyObject *obj, if (cidobj == NULL) { return -1; } - if (_channelid_shared(tstate, cidobj, data) < 0) { + int res = _channelid_shared(tstate, cidobj, data); + Py_DECREF(cidobj); + if (res < 0) { return -1; } data->new_object = _channel_end_from_xid; @@ -2464,7 +2468,10 @@ channel__channel_id(PyObject *self, PyObject *args, PyObject *kwds) return NULL; } PyTypeObject *cls = state->ChannelIDType; - assert(get_module_from_owned_type(cls) == self); + + PyObject *mod = get_module_from_owned_type(cls); + assert(mod == self); + Py_DECREF(mod); return _channelid_new(self, cls, args, kwds); } |