self.assertEqual([b"abcdef", b"middle", b"g"*chunk_size],
buf._write_stack)
+ def test_issue142594(self):
+ wrapper = None
+ detached = False
+ class ReentrantRawIO(self.RawIOBase):
+ @property
+ def closed(self):
+ nonlocal detached
+ if wrapper is not None and not detached:
+ detached = True
+ wrapper.detach()
+ return False
+
+ raw = ReentrantRawIO()
+ wrapper = self.TextIOWrapper(raw)
+ wrapper.close() # should not crash
+
class PyTextIOWrapperTest(TextIOWrapperTest):
io = pyio
--- /dev/null
+Fix crash in ``TextIOWrapper.close()`` when the underlying buffer's
+``closed`` property calls :meth:`~io.TextIOBase.detach`.
if (r > 0) {
Py_RETURN_NONE; /* stream already closed */
}
+ if (self->detached) {
+ Py_RETURN_NONE; /* gh-142594 null pointer issue */
+ }
else {
PyObject *exc = NULL;
if (self->finalizing) {