@@ -957,7 +957,7 @@ _Py_open_impl(const char *pathname, int flags, int gil_held)
957957
958958 The file descriptor is created non-inheritable.
959959
960- The GIL must be held. Use _Py_open_noraise() if the GIL cannot be held. */
960+ The GIL must be held. */
961961int
962962_Py_open (const char * pathname , int flags )
963963{
@@ -977,8 +977,9 @@ _Py_open_noraise(const char *pathname, int flags)
977977}
978978
979979/* Open a file. Use _wfopen() on Windows, encode the path to the locale
980- encoding and use fopen() otherwise. The file descriptor is created
981- non-inheritable. */
980+ encoding and use fopen() otherwise.
981+
982+ The file descriptor is created non-inheritable). */
982983FILE *
983984_Py_wfopen (const wchar_t * path , const wchar_t * mode )
984985{
@@ -1009,7 +1010,9 @@ _Py_wfopen(const wchar_t *path, const wchar_t *mode)
10091010 return f ;
10101011}
10111012
1012- /* Wrapper to fopen(). The file descriptor is created non-inheritable. */
1013+ /* Wrapper to fopen().
1014+
1015+ The file descriptor is created non-inheritable). */
10131016FILE *
10141017_Py_fopen (const char * pathname , const char * mode )
10151018{
@@ -1024,11 +1027,14 @@ _Py_fopen(const char *pathname, const char *mode)
10241027}
10251028
10261029/* Open a file. Call _wfopen() on Windows, or encode the path to the filesystem
1027- encoding and call fopen() otherwise. The file descriptor is created
1028- non-inheritable.
1030+ encoding and call fopen() otherwise.
1031+
1032+ Return the new file object on success. Raise an exception and return NULL
1033+ on error.
10291034
1030- Return the new file object on success, or NULL if the file cannot be open or
1031- (if PyErr_Occurred()) on unicode error. */
1035+ The file descriptor is created non-inheritable.
1036+
1037+ The GIL must be held. */
10321038FILE *
10331039_Py_fopen_obj (PyObject * path , const char * mode )
10341040{
@@ -1038,6 +1044,8 @@ _Py_fopen_obj(PyObject *path, const char *mode)
10381044 wchar_t wmode [10 ];
10391045 int usize ;
10401046
1047+ assert (PyGILState_Check ());
1048+
10411049 if (!PyUnicode_Check (path )) {
10421050 PyErr_Format (PyExc_TypeError ,
10431051 "str file path expected under Windows, got %R" ,
@@ -1049,20 +1057,36 @@ _Py_fopen_obj(PyObject *path, const char *mode)
10491057 return NULL ;
10501058
10511059 usize = MultiByteToWideChar (CP_ACP , 0 , mode , -1 , wmode , sizeof (wmode ));
1052- if (usize == 0 )
1060+ if (usize == 0 ) {
1061+ PyErr_SetFromWindowsErr (0 );
10531062 return NULL ;
1063+ }
10541064
1065+ Py_BEGIN_ALLOW_THREADS
10551066 f = _wfopen (wpath , wmode );
1067+ Py_END_ALLOW_THREADS
10561068#else
10571069 PyObject * bytes ;
1070+ char * path_bytes ;
1071+
1072+ assert (PyGILState_Check ());
1073+
10581074 if (!PyUnicode_FSConverter (path , & bytes ))
10591075 return NULL ;
1060- f = fopen (PyBytes_AS_STRING (bytes ), mode );
1076+ path_bytes = PyBytes_AS_STRING (bytes );
1077+
1078+ Py_BEGIN_ALLOW_THREADS
1079+ f = fopen (path_bytes , mode );
1080+ Py_END_ALLOW_THREADS
1081+
10611082 Py_DECREF (bytes );
10621083#endif
1063- if (f == NULL )
1084+ if (f == NULL ) {
1085+ PyErr_SetFromErrnoWithFilenameObject (PyExc_OSError , path );
10641086 return NULL ;
1065- if (make_non_inheritable (fileno (f )) < 0 ) {
1087+ }
1088+
1089+ if (set_inheritable (fileno (f ), 0 , 1 , NULL ) < 0 ) {
10661090 fclose (f );
10671091 return NULL ;
10681092 }
0 commit comments