Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8be6be4

Browse files
Issue #21802: The reader in BufferedRWPair now is closed even when closing
writer failed in BufferedRWPair.close().
2 parents a54aae0 + 7665be6 commit 8be6be4

4 files changed

Lines changed: 64 additions & 6 deletions

File tree

Lib/_pyio.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,8 +1291,10 @@ def flush(self):
12911291
return self.writer.flush()
12921292

12931293
def close(self):
1294-
self.writer.close()
1295-
self.reader.close()
1294+
try:
1295+
self.writer.close()
1296+
finally:
1297+
self.reader.close()
12961298

12971299
def isatty(self):
12981300
return self.reader.isatty() or self.writer.isatty()

Lib/test/test_io.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1649,6 +1649,53 @@ def test_close_and_closed(self):
16491649
pair.close()
16501650
self.assertTrue(pair.closed)
16511651

1652+
def test_reader_close_error_on_close(self):
1653+
def reader_close():
1654+
reader_non_existing
1655+
reader = self.MockRawIO()
1656+
reader.close = reader_close
1657+
writer = self.MockRawIO()
1658+
pair = self.tp(reader, writer)
1659+
with self.assertRaises(NameError) as err:
1660+
pair.close()
1661+
self.assertIn('reader_non_existing', str(err.exception))
1662+
self.assertTrue(pair.closed)
1663+
self.assertFalse(reader.closed)
1664+
self.assertTrue(writer.closed)
1665+
1666+
def test_writer_close_error_on_close(self):
1667+
def writer_close():
1668+
writer_non_existing
1669+
reader = self.MockRawIO()
1670+
writer = self.MockRawIO()
1671+
writer.close = writer_close
1672+
pair = self.tp(reader, writer)
1673+
with self.assertRaises(NameError) as err:
1674+
pair.close()
1675+
self.assertIn('writer_non_existing', str(err.exception))
1676+
self.assertFalse(pair.closed)
1677+
self.assertTrue(reader.closed)
1678+
self.assertFalse(writer.closed)
1679+
1680+
def test_reader_writer_close_error_on_close(self):
1681+
def reader_close():
1682+
reader_non_existing
1683+
def writer_close():
1684+
writer_non_existing
1685+
reader = self.MockRawIO()
1686+
reader.close = reader_close
1687+
writer = self.MockRawIO()
1688+
writer.close = writer_close
1689+
pair = self.tp(reader, writer)
1690+
with self.assertRaises(NameError) as err:
1691+
pair.close()
1692+
self.assertIn('reader_non_existing', str(err.exception))
1693+
self.assertIsInstance(err.exception.__context__, NameError)
1694+
self.assertIn('writer_non_existing', str(err.exception.__context__))
1695+
self.assertFalse(pair.closed)
1696+
self.assertFalse(reader.closed)
1697+
self.assertFalse(writer.closed)
1698+
16521699
def test_isatty(self):
16531700
class SelectableIsAtty(MockRawIO):
16541701
def __init__(self, isatty):

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ Core and Builtins
3030
Library
3131
-------
3232

33+
- Issue #21802: The reader in BufferedRWPair now is closed even when closing
34+
writer failed in BufferedRWPair.close().
35+
3336
- Issue #23622: Unknown escapes in regular expressions that consist of ``'\'``
3437
and ASCII letter now raise a deprecation warning and will be forbidden in
3538
Python 3.6.

Modules/_io/bufferedio.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2413,12 +2413,18 @@ bufferedrwpair_writable(rwpair *self, PyObject *args)
24132413
static PyObject *
24142414
bufferedrwpair_close(rwpair *self, PyObject *args)
24152415
{
2416+
PyObject *exc = NULL, *val, *tb;
24162417
PyObject *ret = _forward_call(self->writer, &PyId_close, args);
24172418
if (ret == NULL)
2418-
return NULL;
2419-
Py_DECREF(ret);
2420-
2421-
return _forward_call(self->reader, &PyId_close, args);
2419+
PyErr_Fetch(&exc, &val, &tb);
2420+
else
2421+
Py_DECREF(ret);
2422+
ret = _forward_call(self->reader, &PyId_close, args);
2423+
if (exc != NULL) {
2424+
_PyErr_ChainExceptions(exc, val, tb);
2425+
Py_CLEAR(ret);
2426+
}
2427+
return ret;
24222428
}
24232429

24242430
static PyObject *

0 commit comments

Comments
 (0)