Blame SOURCES/00287-fix-thread-hanging-on-inaccessible-nfs-server.patch

925e6b
diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c
925e6b
index 4a71a57ec0d..2b40ada195a 100644
925e6b
--- a/Modules/_io/fileio.c
925e6b
+++ b/Modules/_io/fileio.c
925e6b
@@ -146,9 +146,15 @@ dircheck(fileio* self, PyObject *nameobj)
925e6b
 {
925e6b
 #if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR)
925e6b
     struct stat buf;
925e6b
+    int res;
925e6b
     if (self->fd < 0)
925e6b
         return 0;
925e6b
-    if (fstat(self->fd, &buf) == 0 && S_ISDIR(buf.st_mode)) {
925e6b
+
925e6b
+    Py_BEGIN_ALLOW_THREADS
925e6b
+    res = fstat(self->fd, &buf;;
925e6b
+    Py_END_ALLOW_THREADS
925e6b
+
925e6b
+    if (res == 0 && S_ISDIR(buf.st_mode)) {
925e6b
         errno = EISDIR;
925e6b
         PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, nameobj);
925e6b
         return -1;
925e6b
@@ -162,17 +168,34 @@ check_fd(int fd)
925e6b
 {
925e6b
 #if defined(HAVE_FSTAT)
925e6b
     struct stat buf;
925e6b
-    if (!_PyVerify_fd(fd) || (fstat(fd, &buf) < 0 && errno == EBADF)) {
925e6b
-        PyObject *exc;
925e6b
-        char *msg = strerror(EBADF);
925e6b
-        exc = PyObject_CallFunction(PyExc_OSError, "(is)",
925e6b
-                                    EBADF, msg);
925e6b
-        PyErr_SetObject(PyExc_OSError, exc);
925e6b
-        Py_XDECREF(exc);
925e6b
-        return -1;
925e6b
+    int res;
925e6b
+    PyObject *exc;
925e6b
+    char *msg;
925e6b
+
925e6b
+    if (!_PyVerify_fd(fd)) {
925e6b
+        goto badfd;
925e6b
     }
925e6b
-#endif
925e6b
+
925e6b
+    Py_BEGIN_ALLOW_THREADS
925e6b
+    res = fstat(fd, &buf;;
925e6b
+    Py_END_ALLOW_THREADS
925e6b
+
925e6b
+    if (res < 0 && errno == EBADF) {
925e6b
+        goto badfd;
925e6b
+    }
925e6b
+
925e6b
     return 0;
925e6b
+
925e6b
+badfd:
925e6b
+    msg = strerror(EBADF);
925e6b
+    exc = PyObject_CallFunction(PyExc_OSError, "(is)",
925e6b
+                                EBADF, msg);
925e6b
+    PyErr_SetObject(PyExc_OSError, exc);
925e6b
+    Py_XDECREF(exc);
925e6b
+    return -1;
925e6b
+#else
925e6b
+    return 0;
925e6b
+#endif
925e6b
 }
925e6b
 
925e6b
 
925e6b
@@ -519,9 +542,19 @@ new_buffersize(fileio *self, size_t currentsize)
925e6b
 #ifdef HAVE_FSTAT
925e6b
     off_t pos, end;
925e6b
     struct stat st;
925e6b
-    if (fstat(self->fd, &st) == 0) {
925e6b
+    int res;
925e6b
+
925e6b
+    Py_BEGIN_ALLOW_THREADS
925e6b
+    res = fstat(self->fd, &st);
925e6b
+    Py_END_ALLOW_THREADS
925e6b
+
925e6b
+    if (res == 0) {
925e6b
         end = st.st_size;
925e6b
+
925e6b
+        Py_BEGIN_ALLOW_THREADS
925e6b
         pos = lseek(self->fd, 0L, SEEK_CUR);
925e6b
+        Py_END_ALLOW_THREADS
925e6b
+
925e6b
         /* Files claiming a size smaller than SMALLCHUNK may
925e6b
            actually be streaming pseudo-files. In this case, we
925e6b
            apply the more aggressive algorithm below.
925e6b
diff --git a/Objects/fileobject.c b/Objects/fileobject.c
925e6b
index 2f63c374d1e..8d1c5812f0d 100644
925e6b
--- a/Objects/fileobject.c
925e6b
+++ b/Objects/fileobject.c
925e6b
@@ -121,10 +121,15 @@ dircheck(PyFileObject* f)
925e6b
 {
925e6b
 #if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR)
925e6b
     struct stat buf;
925e6b
+    int res;
925e6b
     if (f->f_fp == NULL)
925e6b
         return f;
925e6b
-    if (fstat(fileno(f->f_fp), &buf) == 0 &&
925e6b
-        S_ISDIR(buf.st_mode)) {
925e6b
+
925e6b
+    Py_BEGIN_ALLOW_THREADS
925e6b
+    res = fstat(fileno(f->f_fp), &buf;;
925e6b
+    Py_END_ALLOW_THREADS
925e6b
+
925e6b
+    if (res == 0 && S_ISDIR(buf.st_mode)) {
925e6b
         char *msg = strerror(EISDIR);
925e6b
         PyObject *exc = PyObject_CallFunction(PyExc_IOError, "(isO)",
925e6b
                                               EISDIR, msg, f->f_name);
925e6b
@@ -1010,7 +1015,13 @@ new_buffersize(PyFileObject *f, size_t currentsize)
925e6b
 #ifdef HAVE_FSTAT
925e6b
     off_t pos, end;
925e6b
     struct stat st;
925e6b
-    if (fstat(fileno(f->f_fp), &st) == 0) {
925e6b
+    int res;
925e6b
+
925e6b
+    Py_BEGIN_ALLOW_THREADS
925e6b
+    res = fstat(fileno(f->f_fp), &st);
925e6b
+    Py_END_ALLOW_THREADS
925e6b
+
925e6b
+    if (res == 0) {
925e6b
         end = st.st_size;
925e6b
         /* The following is not a bug: we really need to call lseek()
925e6b
            *and* ftell().  The reason is that some stdio libraries
925e6b
@@ -1021,7 +1032,11 @@ new_buffersize(PyFileObject *f, size_t currentsize)
925e6b
            works.  We can't use the lseek() value either, because we
925e6b
            need to take the amount of buffered data into account.
925e6b
            (Yet another reason why stdio stinks. :-) */
925e6b
+
925e6b
+        Py_BEGIN_ALLOW_THREADS
925e6b
         pos = lseek(fileno(f->f_fp), 0L, SEEK_CUR);
925e6b
+        Py_END_ALLOW_THREADS
925e6b
+
925e6b
         if (pos >= 0) {
925e6b
             pos = ftell(f->f_fp);
925e6b
         }