diff options
author | Nir Soffer <nirsof@gmail.com> | 2017-12-01 01:18:58 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2017-12-01 01:18:58 (GMT) |
commit | 6a89481680b921e7b317c29877bdda9a6031e5ad (patch) | |
tree | d5292d62fba5e604eda83869670acde7c51db492 | |
parent | c319eeeb45043ee45384b8064c53ddbfde1673cd (diff) | |
download | cpython-6a89481680b921e7b317c29877bdda9a6031e5ad.zip cpython-6a89481680b921e7b317c29877bdda9a6031e5ad.tar.gz cpython-6a89481680b921e7b317c29877bdda9a6031e5ad.tar.bz2 |
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.
-rw-r--r-- | Misc/NEWS.d/next/Library/2017-11-30-20-38-16.bpo-32186.O42bVe.rst | 3 | ||||
-rw-r--r-- | Modules/_io/fileio.c | 6 |
2 files changed, 8 insertions, 1 deletions
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; |