Issue #21802: The reader in BufferedRWPair now is closed even when closing

writer failed in BufferedRWPair.close().
This commit is contained in:
Serhiy Storchaka 2015-03-24 23:23:42 +02:00
parent 40fd0e8d68
commit f95a57f9a1
4 changed files with 69 additions and 6 deletions

View File

@ -1216,8 +1216,10 @@ class BufferedRWPair(BufferedIOBase):
return self.writer.flush() return self.writer.flush()
def close(self): def close(self):
self.writer.close() try:
self.reader.close() self.writer.close()
finally:
self.reader.close()
def isatty(self): def isatty(self):
return self.reader.isatty() or self.writer.isatty() return self.reader.isatty() or self.writer.isatty()

View File

@ -1495,6 +1495,51 @@ class BufferedRWPairTest(unittest.TestCase):
pair.close() pair.close()
self.assertTrue(pair.closed) self.assertTrue(pair.closed)
def test_reader_close_error_on_close(self):
def reader_close():
reader_non_existing
reader = self.MockRawIO()
reader.close = reader_close
writer = self.MockRawIO()
pair = self.tp(reader, writer)
with self.assertRaises(NameError) as err:
pair.close()
self.assertIn('reader_non_existing', str(err.exception))
self.assertTrue(pair.closed)
self.assertFalse(reader.closed)
self.assertTrue(writer.closed)
def test_writer_close_error_on_close(self):
def writer_close():
writer_non_existing
reader = self.MockRawIO()
writer = self.MockRawIO()
writer.close = writer_close
pair = self.tp(reader, writer)
with self.assertRaises(NameError) as err:
pair.close()
self.assertIn('writer_non_existing', str(err.exception))
self.assertFalse(pair.closed)
self.assertTrue(reader.closed)
self.assertFalse(writer.closed)
def test_reader_writer_close_error_on_close(self):
def reader_close():
reader_non_existing
def writer_close():
writer_non_existing
reader = self.MockRawIO()
reader.close = reader_close
writer = self.MockRawIO()
writer.close = writer_close
pair = self.tp(reader, writer)
with self.assertRaises(NameError) as err:
pair.close()
self.assertIn('reader_non_existing', str(err.exception))
self.assertFalse(pair.closed)
self.assertFalse(reader.closed)
self.assertFalse(writer.closed)
def test_isatty(self): def test_isatty(self):
class SelectableIsAtty(MockRawIO): class SelectableIsAtty(MockRawIO):
def __init__(self, isatty): def __init__(self, isatty):

View File

@ -21,6 +21,9 @@ Core and Builtins
Library Library
------- -------
- Issue #21802: The reader in BufferedRWPair now is closed even when closing
writer failed in BufferedRWPair.close().
- Issue #23671: string.Template now allows to specify the "self" parameter as - Issue #23671: string.Template now allows to specify the "self" parameter as
keyword argument. string.Formatter now allows to specify the "self" and keyword argument. string.Formatter now allows to specify the "self" and
the "format_string" parameters as keyword arguments. the "format_string" parameters as keyword arguments.

View File

@ -2200,12 +2200,25 @@ bufferedrwpair_writable(rwpair *self, PyObject *args)
static PyObject * static PyObject *
bufferedrwpair_close(rwpair *self, PyObject *args) bufferedrwpair_close(rwpair *self, PyObject *args)
{ {
PyObject *exc = NULL, *val, *tb;
PyObject *ret = _forward_call(self->writer, "close", args); PyObject *ret = _forward_call(self->writer, "close", args);
if (ret == NULL) if (ret == NULL)
return NULL; PyErr_Fetch(&exc, &val, &tb);
Py_DECREF(ret); else
Py_DECREF(ret);
return _forward_call(self->reader, "close", args); ret = _forward_call(self->reader, "close", args);
if (exc != NULL) {
if (ret != NULL) {
Py_CLEAR(ret);
PyErr_Restore(exc, val, tb);
}
else {
Py_DECREF(exc);
Py_XDECREF(val);
Py_XDECREF(tb);
}
}
return ret;
} }
static PyObject * static PyObject *