https://github.com/python/cpython/commit/e54507374b0fb2b13c0800b4e4c132c3317e90c0
commit: e54507374b0fb2b13c0800b4e4c132c3317e90c0
branch: 3.13
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-02-18T14:18:39Z
summary:
[3.13] gh-140652: Fix a crash in _interpchannels.list_all() after clo…sing a
channel (GH-143743) (GH-144953)
(cherry picked from commit 3f50432e31c8e0d2e3ea8cbc2e472f7ee80e327a)
files:
A Misc/NEWS.d/next/Library/2026-01-12-19-39-57.gh-issue-140652.HvM9Bl.rst
M Lib/test/test__interpchannels.py
M Lib/test/test_interpreters/test_channels.py
M Modules/_interpchannelsmodule.c
diff --git a/Lib/test/test__interpchannels.py b/Lib/test/test__interpchannels.py
index 4a7f04b9df9843..e54c69c97d62ff 100644
--- a/Lib/test/test__interpchannels.py
+++ b/Lib/test/test__interpchannels.py
@@ -382,6 +382,38 @@ def test_sequential_ids(self):
self.assertEqual(id3, int(id2) + 1)
self.assertEqual(set(after) - set(before), {id1, id2, id3})
+ def test_channel_list_all_closed(self):
+ id1 = _channels.create(REPLACE)
+ id2 = _channels.create(REPLACE)
+ id3 = _channels.create(REPLACE)
+ before = _channels.list_all()
+ expected = [info for info in before if info[0] != id2]
+ _channels.close(id2, force=True)
+ after = _channels.list_all()
+ self.assertEqual(set(after), set(expected))
+ self.assertEqual(len(after), len(before) - 1)
+
+ def test_channel_list_all_destroyed(self):
+ id1 = _channels.create(REPLACE)
+ id2 = _channels.create(REPLACE)
+ id3 = _channels.create(REPLACE)
+ before = _channels.list_all()
+ expected = [info for info in before if info[0] != id2]
+ _channels.destroy(id2)
+ after = _channels.list_all()
+ self.assertEqual(set(after), set(expected))
+ self.assertEqual(len(after), len(before) - 1)
+
+ def test_channel_list_all_released(self):
+ id1 = _channels.create(REPLACE)
+ id2 = _channels.create(REPLACE)
+ id3 = _channels.create(REPLACE)
+ before = _channels.list_all()
+ _channels.release(id2, send=True, recv=True)
+ after = _channels.list_all()
+ self.assertEqual(set(after), set(before))
+ self.assertEqual(len(after), len(before))
+
def test_ids_global(self):
id1 = _interpreters.create()
out = _run_output(id1, dedent("""
diff --git a/Lib/test/test_interpreters/test_channels.py
b/Lib/test/test_interpreters/test_channels.py
index eada18f99d04db..96d83973b9c9e6 100644
--- a/Lib/test/test_interpreters/test_channels.py
+++ b/Lib/test/test_interpreters/test_channels.py
@@ -47,6 +47,12 @@ def test_list_all(self):
after = set(channels.list_all())
self.assertEqual(after, created)
+ def test_list_all_closed(self):
+ created = [channels.create() for _ in range(3)]
+ rch, sch = created.pop(1)
+ rch.close()
+ self.assertEqual(set(channels.list_all()), set(created))
+
def test_shareable(self):
interp = interpreters.create()
rch, sch = channels.create()
diff --git
a/Misc/NEWS.d/next/Library/2026-01-12-19-39-57.gh-issue-140652.HvM9Bl.rst
b/Misc/NEWS.d/next/Library/2026-01-12-19-39-57.gh-issue-140652.HvM9Bl.rst
new file mode 100644
index 00000000000000..bed126f02f8714
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-01-12-19-39-57.gh-issue-140652.HvM9Bl.rst
@@ -0,0 +1 @@
+Fix a crash in :func:`!_interpchannels.list_all` after closing a channel.
diff --git a/Modules/_interpchannelsmodule.c b/Modules/_interpchannelsmodule.c
index 2b429a252a8ec2..460b4e5f4ea4f0 100644
--- a/Modules/_interpchannelsmodule.c
+++ b/Modules/_interpchannelsmodule.c
@@ -1626,14 +1626,16 @@ _channels_list_all(_channels *channels, int64_t *count)
if (ids == NULL) {
goto done;
}
- _channelref *ref = channels->head;
- for (int64_t i=0; ref != NULL; ref = ref->next, i++) {
- ids[i] = (struct channel_id_and_info){
- .id = ref->cid,
- .unboundop = ref->chan->defaults.unboundop,
- };
+ int64_t i = 0;
+ for (_channelref *ref = channels->head; ref != NULL; ref = ref->next) {
+ if (ref->chan != NULL) {
+ ids[i++] = (struct channel_id_and_info){
+ .id = ref->cid,
+ .unboundop = ref->chan->defaults.unboundop,
+ };
+ }
}
- *count = channels->numopen;
+ *count = i;
cids = ids;
done:
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]