]> granicus.if.org Git - python/commitdiff
Issue #25717: Tolerate fstat() failures in the FileIO constructor
authorMartin Panter <vadmium+py@gmail.com>
Sun, 6 Dec 2015 03:15:05 +0000 (03:15 +0000)
committerMartin Panter <vadmium+py@gmail.com>
Sun, 6 Dec 2015 03:15:05 +0000 (03:15 +0000)
This restores 3.4 behaviour, which was removed by revision 3b5279b5bfd1. The
fstat() call fails with ENOENT for a Virtual Box shared folder filesystem if
the file entry has been unlinked, e.g. for a temporary file.

Misc/NEWS
Modules/_io/fileio.c

index 4399da2490c7e9a93ce1c74b341f6474f1df93f7..f8680377f394f50466ce833270b8e193e615541a 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -22,6 +22,10 @@ Core and Builtins
 Library
 -------
 
+- Issue #25717: Restore the previous behaviour of tolerating most fstat()
+  errors when opening files.  This was a regression in 3.5a1, and stopped
+  anonymous temporary files from working in special cases.
+
 - Issue #24903: Fix regression in number of arguments compileall accepts when
   '-d' is specified.  The check on the number of arguments has been dropped
   completely as it never worked correctly anyway.
index 12e37bbbbe1e938e2d98c959f97ee5c31a2c50c4..5f88d58c45a455b101f947702b524b47475189ff 100644 (file)
@@ -250,6 +250,7 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode,
     int *atomic_flag_works = NULL;
 #endif
     struct _Py_stat_struct fdfstat;
+    int fstat_result;
     int async_err = 0;
 
     assert(PyFileIO_Check(self));
@@ -438,22 +439,36 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode,
     }
 
     self->blksize = DEFAULT_BUFFER_SIZE;
-    if (_Py_fstat(self->fd, &fdfstat) < 0)
-        goto error;
-#if defined(S_ISDIR) && defined(EISDIR)
-    /* On Unix, open will succeed for directories.
-       In Python, there should be no file objects referring to
-       directories, so we need a check.  */
-    if (S_ISDIR(fdfstat.st_mode)) {
-        errno = EISDIR;
-        PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, nameobj);
-        goto error;
+    Py_BEGIN_ALLOW_THREADS
+    fstat_result = _Py_fstat_noraise(self->fd, &fdfstat);
+    Py_END_ALLOW_THREADS
+    if (fstat_result < 0) {
+#ifdef MS_WINDOWS
+        if (GetLastError() == ERROR_INVALID_HANDLE) {
+            PyErr_SetFromWindowsErr(0);
+#else
+        if (errno == EBADF) {
+            PyErr_SetFromErrno(PyExc_OSError);
+#endif
+            goto error;
+        }
     }
+    else {
+#if defined(S_ISDIR) && defined(EISDIR)
+        /* On Unix, open will succeed for directories.
+           In Python, there should be no file objects referring to
+           directories, so we need a check.  */
+        if (S_ISDIR(fdfstat.st_mode)) {
+            errno = EISDIR;
+            PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, nameobj);
+            goto error;
+        }
 #endif /* defined(S_ISDIR) */
 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
-    if (fdfstat.st_blksize > 1)
-        self->blksize = fdfstat.st_blksize;
+        if (fdfstat.st_blksize > 1)
+            self->blksize = fdfstat.st_blksize;
 #endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
+    }
 
 #if defined(MS_WINDOWS) || defined(__CYGWIN__)
     /* don't translate newlines (\r\n <=> \n) */