diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2015-03-18 00:39:23 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2015-03-18 00:39:23 (GMT) |
commit | e42ccd2bfd7a05a02c1020b819e4ee5b26041d01 (patch) | |
tree | 071843848770176c8aed3f965d783738182847c3 /Python | |
parent | a555cfcb73cf677a99d29af6fa0bcfe4c35a2aeb (diff) | |
download | cpython-e42ccd2bfd7a05a02c1020b819e4ee5b26041d01.zip cpython-e42ccd2bfd7a05a02c1020b819e4ee5b26041d01.tar.gz cpython-e42ccd2bfd7a05a02c1020b819e4ee5b26041d01.tar.bz2 |
Issue #23694: Enhance _Py_fopen(), it now raises an exception on error
* If fopen() fails, OSError is raised with the original filename object.
* The GIL is now released while calling fopen()
Diffstat (limited to 'Python')
-rw-r--r-- | Python/errors.c | 4 | ||||
-rw-r--r-- | Python/fileutils.c | 48 | ||||
-rw-r--r-- | Python/import.c | 2 |
3 files changed, 40 insertions, 14 deletions
diff --git a/Python/errors.c b/Python/errors.c index 940aef3..1d64efd 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -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); } diff --git a/Python/fileutils.c b/Python/fileutils.c index 7686040..a198625 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -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; } diff --git a/Python/import.c b/Python/import.c index c3b9e12..238e8d0 100644 --- a/Python/import.c +++ b/Python/import.c @@ -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; } } |