From 6a89481680b921e7b317c29877bdda9a6031e5ad Mon Sep 17 00:00:00 2001 From: Nir Soffer Date: Fri, 1 Dec 2017 03:18:58 +0200 Subject: bpo-32186: Release the GIL during lseek and fstat (#4652) In _io_FileIO_readall_impl(), lseek() and _Py_fstat_noraise() were called without releasing the GIL. This can cause all threads to hang for unlimited time when calling FileIO.read() and the NFS server is not accessible. --- Misc/NEWS.d/next/Library/2017-11-30-20-38-16.bpo-32186.O42bVe.rst | 3 +++ Modules/_io/fileio.c | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2017-11-30-20-38-16.bpo-32186.O42bVe.rst diff --git a/Misc/NEWS.d/next/Library/2017-11-30-20-38-16.bpo-32186.O42bVe.rst b/Misc/NEWS.d/next/Library/2017-11-30-20-38-16.bpo-32186.O42bVe.rst new file mode 100644 index 0000000..ea696c6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-11-30-20-38-16.bpo-32186.O42bVe.rst @@ -0,0 +1,3 @@ +io.FileIO.readall() and io.FileIO.read() now release the GIL when +getting the file size. Fixed hang of all threads with inaccessible NFS +server. Patch by Nir Soffer. diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index b6755b8..269142c 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -683,10 +683,12 @@ _io_FileIO_readall_impl(fileio *self) Py_ssize_t bytes_read = 0; Py_ssize_t n; size_t bufsize; + int fstat_result; if (self->fd < 0) return err_closed(); + Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH #ifdef MS_WINDOWS pos = _lseeki64(self->fd, 0L, SEEK_CUR); @@ -694,8 +696,10 @@ _io_FileIO_readall_impl(fileio *self) pos = lseek(self->fd, 0L, SEEK_CUR); #endif _Py_END_SUPPRESS_IPH + fstat_result = _Py_fstat_noraise(self->fd, &status); + Py_END_ALLOW_THREADS - if (_Py_fstat_noraise(self->fd, &status) == 0) + if (fstat_result == 0) end = status.st_size; else end = (Py_off_t)-1; -- cgit v0.12