New submission from David Beazley: First comment: In the I/O library, there is documented behavior for how things work in the presence of non-blocking I/O. For example, read/write methods returning None on raw file objects. Methods on BufferedIO instances raise a BlockingIOError for operations that can't complete.
However, the implementation of close() is currently broken. If buffered I/O is being used and a file is closed, it's possible that the close will fail due to a BlockingIOError occurring as buffered data is flushed to output. However, in this case, the file is closed anyways and there is no possibility to retry. Here is an example to illustrate: >>> from socket import * >>> s = socket(AF_INET, SOCK_STREAM) >>> s.connect(('somehost', port)) >>> s.setblocking(False) >>> f = s.makefile('wb', buffering=10000000) # Large buffer >>> f.write(b'x'*1000000) >>> Now, watch carefully >>> f <_io.BufferedWriter name=4> >>> f.closed False >>> f.close() Traceback (most recent call last): File "<stdin>", line 1, in <module> BlockingIOError: [Errno 35] write could not complete without blocking >>> f <_io.BufferedWriter name=-1> >>> f.closed True >>> I believe this can be fixed by changing a single line in Modules/_io/bufferedio.c: --- bufferedio_orig.c 2015-10-25 16:40:22.000000000 -0500 +++ bufferedio.c 2015-10-25 16:40:35.000000000 -0500 @@ -530,10 +530,10 @@ res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL); if (!ENTER_BUFFERED(self)) return NULL; - if (res == NULL) - PyErr_Fetch(&exc, &val, &tb); - else - Py_DECREF(res); + if (res == NULL) + goto end; + else + Py_DECREF(res); res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL); With this patch, the close() method can be retried as appropriate until all buffered data is successfully written. ---------- components: IO messages: 253438 nosy: dabeaz priority: normal severity: normal status: open title: close() behavior on non-blocking BufferedIO objects with sockets type: behavior versions: Python 3.5 _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue25476> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com