[Python-checkins] bpo-32186: Release the GIL during lseek and fstat (#4652)

Victor Stinner webhook-mailer at python.org
Thu Nov 30 20:19:01 EST 2017


https://github.com/python/cpython/commit/6a89481680b921e7b317c29877bdda9a6031e5ad
commit: 6a89481680b921e7b317c29877bdda9a6031e5ad
branch: master
author: Nir Soffer <nirsof at gmail.com>
committer: Victor Stinner <victor.stinner at gmail.com>
date: 2017-12-01T02:18:58+01:00
summary:

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.

files:
A Misc/NEWS.d/next/Library/2017-11-30-20-38-16.bpo-32186.O42bVe.rst
M Modules/_io/fileio.c

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 00000000000..ea696c6098a
--- /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 b6755b851dc..269142cfee5 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;



More information about the Python-checkins mailing list