Skip to content

Commit d5ec6d6

Browse files
gh-140652: Fix a crash in _interpchannels.list_all() after closing a channel
1 parent e535bdb commit d5ec6d6

File tree

4 files changed

+48
-7
lines changed

4 files changed

+48
-7
lines changed

Lib/test/test__interpchannels.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,38 @@ def test_sequential_ids(self):
382382
self.assertEqual(id3, int(id2) + 1)
383383
self.assertEqual(set(after) - set(before), {id1, id2, id3})
384384

385+
def test_channel_list_all_closed(self):
386+
id1 = _channels.create()
387+
id2 = _channels.create()
388+
id3 = _channels.create()
389+
before = _channels.list_all()
390+
expected = [info for info in before if info[0] != id2]
391+
_channels.close(id2, force=True)
392+
after = _channels.list_all()
393+
self.assertEqual(set(after), set(expected))
394+
self.assertEqual(len(after), len(before) - 1)
395+
396+
def test_channel_list_all_destroyed(self):
397+
id1 = _channels.create()
398+
id2 = _channels.create()
399+
id3 = _channels.create()
400+
before = _channels.list_all()
401+
expected = [info for info in before if info[0] != id2]
402+
_channels.destroy(id2)
403+
after = _channels.list_all()
404+
self.assertEqual(set(after), set(expected))
405+
self.assertEqual(len(after), len(before) - 1)
406+
407+
def test_channel_list_all_released(self):
408+
id1 = _channels.create()
409+
id2 = _channels.create()
410+
id3 = _channels.create()
411+
before = _channels.list_all()
412+
_channels.release(id2, send=True, recv=True)
413+
after = _channels.list_all()
414+
self.assertEqual(set(after), set(before))
415+
self.assertEqual(len(after), len(before))
416+
385417
def test_ids_global(self):
386418
id1 = _interpreters.create()
387419
out = _run_output(id1, dedent("""

Lib/test/test_interpreters/test_channels.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ def test_list_all(self):
4747
after = set(channels.list_all())
4848
self.assertEqual(after, created)
4949

50+
def test_list_all_closed(self):
51+
created = [channels.create() for _ in range(3)]
52+
rch, sch = created.pop(1)
53+
rch.close()
54+
self.assertEqual(set(channels.list_all()), set(created))
55+
5056
def test_shareable(self):
5157
interp = interpreters.create()
5258
rch, sch = channels.create()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a crash in :func:`!_interpchannels.list_all` after closing a channel.

Modules/_interpchannelsmodule.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1644,14 +1644,16 @@ _channels_list_all(_channels *channels, int64_t *count)
16441644
if (ids == NULL) {
16451645
goto done;
16461646
}
1647-
_channelref *ref = channels->head;
1648-
for (int64_t i=0; ref != NULL; ref = ref->next, i++) {
1649-
ids[i] = (struct channel_id_and_info){
1650-
.id = ref->cid,
1651-
.defaults = ref->chan->defaults,
1652-
};
1647+
int64_t i = 0;
1648+
for (_channelref *ref = channels->head; ref != NULL; ref = ref->next) {
1649+
if (ref->chan != NULL) {
1650+
ids[i++] = (struct channel_id_and_info){
1651+
.id = ref->cid,
1652+
.defaults = ref->chan->defaults,
1653+
};
1654+
}
16531655
}
1654-
*count = channels->numopen;
1656+
*count = i;
16551657

16561658
cids = ids;
16571659
done:

0 commit comments

Comments
 (0)