]> granicus.if.org Git - python/commitdiff
Issue #23694: Enhance _Py_fopen(), it now raises an exception on error
authorVictor Stinner <victor.stinner@gmail.com>
Wed, 18 Mar 2015 00:39:23 +0000 (01:39 +0100)
committerVictor Stinner <victor.stinner@gmail.com>
Wed, 18 Mar 2015 00:39:23 +0000 (01:39 +0100)
* If fopen() fails, OSError is raised with the original filename object.
* The GIL is now released while calling fopen()

Modules/_ssl.c
Modules/zipimport.c
Python/errors.c
Python/fileutils.c
Python/import.c

index 8596225cbfa9b475a4b9555349001371683c585f..fb03513d89b02ddafe5fa8631a285ff49aa49711 100644 (file)
@@ -2941,11 +2941,9 @@ load_dh_params(PySSLContext *self, PyObject *filepath)
     DH *dh;
 
     f = _Py_fopen_obj(filepath, "rb");
-    if (f == NULL) {
-        if (!PyErr_Occurred())
-            PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, filepath);
+    if (f == NULL)
         return NULL;
-    }
+
     errno = 0;
     PySSL_BEGIN_ALLOW_THREADS
     dh = PEM_read_DHparams(f, NULL, NULL, NULL);
index f2cc245b7d88d24f0b8b223781c2da2c70e8b038..f5ac10beb0b55490982424bab2fe10824ddbbbd5 100644 (file)
@@ -875,7 +875,7 @@ read_directory(PyObject *archive)
 
     fp = _Py_fopen_obj(archive, "rb");
     if (fp == NULL) {
-        if (!PyErr_Occurred())
+        if (PyErr_ExceptionMatches(PyExc_OSError))
             PyErr_Format(ZipImportError, "can't open Zip file: %R", archive);
         return NULL;
     }
@@ -1073,12 +1073,8 @@ get_data(PyObject *archive, PyObject *toc_entry)
     }
 
     fp = _Py_fopen_obj(archive, "rb");
-    if (!fp) {
-        if (!PyErr_Occurred())
-            PyErr_Format(PyExc_IOError,
-               "zipimport: can not open file %U", archive);
+    if (!fp)
         return NULL;
-    }
 
     /* Check to make sure the local file header is correct */
     if (fseek(fp, file_offset, 0) == -1) {
index 940aef33a200f0b2a641fa304dd3f3446bc926f1..1d64efd3158b928ed4c81e4e807d1323ad708e9d 100644 (file)
@@ -1126,6 +1126,10 @@ PyErr_ProgramTextObject(PyObject *filename, int lineno)
     if (filename == NULL || lineno <= 0)
         return NULL;
     fp = _Py_fopen_obj(filename, "r" PY_STDIOTEXTMODE);
+    if (fp == NULL) {
+        PyErr_Clear();
+        return NULL;
+    }
     return err_programtext(fp, lineno);
 }
 
index 76860406b2786ee2754cdfa69907232479819f68..a198625afaeefab317c093be489e9dc74d94894a 100644 (file)
@@ -957,7 +957,7 @@ _Py_open_impl(const char *pathname, int flags, int gil_held)
 
    The file descriptor is created non-inheritable.
 
-   The GIL must be held. Use _Py_open_noraise() if the GIL cannot be held. */
+   The GIL must be held. */
 int
 _Py_open(const char *pathname, int flags)
 {
@@ -977,8 +977,9 @@ _Py_open_noraise(const char *pathname, int flags)
 }
 
 /* Open a file. Use _wfopen() on Windows, encode the path to the locale
-   encoding and use fopen() otherwise. The file descriptor is created
-   non-inheritable. */
+   encoding and use fopen() otherwise.
+
+   The file descriptor is created non-inheritable). */
 FILE *
 _Py_wfopen(const wchar_t *path, const wchar_t *mode)
 {
@@ -1009,7 +1010,9 @@ _Py_wfopen(const wchar_t *path, const wchar_t *mode)
     return f;
 }
 
-/* Wrapper to fopen(). The file descriptor is created non-inheritable. */
+/* Wrapper to fopen().
+
+   The file descriptor is created non-inheritable). */
 FILE*
 _Py_fopen(const char *pathname, const char *mode)
 {
@@ -1024,11 +1027,14 @@ _Py_fopen(const char *pathname, const char *mode)
 }
 
 /* Open a file. Call _wfopen() on Windows, or encode the path to the filesystem
-   encoding and call fopen() otherwise. The file descriptor is created
-   non-inheritable.
+   encoding and call fopen() otherwise.
+
+   Return the new file object on success. Raise an exception and return NULL
+   on error.
 
-   Return the new file object on success, or NULL if the file cannot be open or
-   (if PyErr_Occurred()) on unicode error. */
+   The file descriptor is created non-inheritable.
+
+   The GIL must be held. */
 FILE*
 _Py_fopen_obj(PyObject *path, const char *mode)
 {
@@ -1038,6 +1044,8 @@ _Py_fopen_obj(PyObject *path, const char *mode)
     wchar_t wmode[10];
     int usize;
 
+    assert(PyGILState_Check());
+
     if (!PyUnicode_Check(path)) {
         PyErr_Format(PyExc_TypeError,
                      "str file path expected under Windows, got %R",
@@ -1049,20 +1057,36 @@ _Py_fopen_obj(PyObject *path, const char *mode)
         return NULL;
 
     usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode));
-    if (usize == 0)
+    if (usize == 0) {
+        PyErr_SetFromWindowsErr(0);
         return NULL;
+    }
 
+    Py_BEGIN_ALLOW_THREADS
     f = _wfopen(wpath, wmode);
+    Py_END_ALLOW_THREADS
 #else
     PyObject *bytes;
+    char *path_bytes;
+
+    assert(PyGILState_Check());
+
     if (!PyUnicode_FSConverter(path, &bytes))
         return NULL;
-    f = fopen(PyBytes_AS_STRING(bytes), mode);
+    path_bytes = PyBytes_AS_STRING(bytes);
+
+    Py_BEGIN_ALLOW_THREADS
+    f = fopen(path_bytes, mode);
+    Py_END_ALLOW_THREADS
+
     Py_DECREF(bytes);
 #endif
-    if (f == NULL)
+    if (f == NULL) {
+        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
         return NULL;
-    if (make_non_inheritable(fileno(f)) < 0) {
+    }
+
+    if (set_inheritable(fileno(f), 0, 1, NULL) < 0) {
         fclose(f);
         return NULL;
     }
index c3b9e12572a730b8d7c12934c8ebdc42bcef8723..238e8d06a1a1c1c324b40fdf9c6b41dd3bfac811 100644 (file)
@@ -1945,8 +1945,6 @@ _imp_load_dynamic_impl(PyModuleDef *module, PyObject *name, PyObject *path, PyOb
         fp = _Py_fopen_obj(path, "r");
         if (fp == NULL) {
             Py_DECREF(path);
-            if (!PyErr_Occurred())
-                PyErr_SetFromErrno(PyExc_IOError);
             return NULL;
         }
     }