From db68bfc771e6a85573732e0b579e8f68841c9b5c Mon Sep 17 00:00:00 2001 From: Cody Maloney Date: Thu, 18 Sep 2025 03:02:29 -0700 Subject: [PATCH] gh-138720: Make Buffered closed check match flush (GH-138724) In `_io__Buffered_flush_impl` the macro `CHECK_CLOSED` is used to check the `buffered*` is in a good state to be flushed. That differs slightly from `buffered_closed`. In some cases, that difference would result in `close()` thinking the file needed to be flushed and closed while `flush()` thought the file was already closed. This could happen during GC and would result in an unraisable exception. --- Lib/test/test_io/test_general.py | 4 ++++ .../Library/2025-09-09-17-57-49.gh-issue-138720.hAtsm-.rst | 4 ++++ Modules/_io/bufferedio.c | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-09-09-17-57-49.gh-issue-138720.hAtsm-.rst diff --git a/Lib/test/test_io/test_general.py b/Lib/test/test_io/test_general.py index c2f0e1877a69..b9abea71e01f 100644 --- a/Lib/test/test_io/test_general.py +++ b/Lib/test/test_io/test_general.py @@ -1980,6 +1980,10 @@ class BufferedRWPairTest: self.assertEqual(getattr(pair, method)(data), 5) self.assertEqual(bytes(data), b"abcde") + # gh-138720: C BufferedRWPair would destruct in a bad order resulting in + # an unraisable exception. + support.gc_collect() + def test_write(self): w = self.MockRawIO() pair = self.tp(self.MockRawIO(), w) diff --git a/Misc/NEWS.d/next/Library/2025-09-09-17-57-49.gh-issue-138720.hAtsm-.rst b/Misc/NEWS.d/next/Library/2025-09-09-17-57-49.gh-issue-138720.hAtsm-.rst new file mode 100644 index 000000000000..4f3f54e1deb8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-09-09-17-57-49.gh-issue-138720.hAtsm-.rst @@ -0,0 +1,4 @@ +Fix an issue where :class:`io.BufferedWriter` and :class:`io.BufferedRandom` +had different definitions of "closed" for :meth:`~io.IOBase.close` and +:meth:`~io.IOBase.flush` which resulted in an exception when close called +flush but flush thought the file was already closed. diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index d0fe7ad61547..2d2559c82192 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -553,8 +553,8 @@ _io__Buffered_close_impl(buffered *self) if (!ENTER_BUFFERED(self)) { return NULL; } - - r = buffered_closed(self); + /* gh-138720: Use IS_CLOSED to match flush CHECK_CLOSED. */ + r = IS_CLOSED(self); if (r < 0) goto end; if (r > 0) { -- 2.47.3