@@ -912,6 +912,7 @@ static int
912912_Py_open_impl (const char * pathname , int flags , int gil_held )
913913{
914914 int fd ;
915+ int async_err = 0 ;
915916#ifndef MS_WINDOWS
916917 int * atomic_flag_works ;
917918#endif
@@ -926,10 +927,14 @@ _Py_open_impl(const char *pathname, int flags, int gil_held)
926927#endif
927928
928929 if (gil_held ) {
929- Py_BEGIN_ALLOW_THREADS
930- fd = open (pathname , flags );
931- Py_END_ALLOW_THREADS
932-
930+ do {
931+ Py_BEGIN_ALLOW_THREADS
932+ fd = open (pathname , flags );
933+ Py_END_ALLOW_THREADS
934+ } while (fd < 0
935+ && errno == EINTR && !(async_err = PyErr_CheckSignals ()));
936+ if (async_err )
937+ return -1 ;
933938 if (fd < 0 ) {
934939 PyErr_SetFromErrnoWithFilename (PyExc_OSError , pathname );
935940 return -1 ;
@@ -957,6 +962,9 @@ _Py_open_impl(const char *pathname, int flags, int gil_held)
957962
958963 The file descriptor is created non-inheritable.
959964
965+ When interrupted by a signal (open() fails with EINTR), retry the syscall,
966+ except if the Python signal handler raises an exception.
967+
960968 The GIL must be held. */
961969int
962970_Py_open (const char * pathname , int flags )
@@ -969,7 +977,9 @@ _Py_open(const char *pathname, int flags)
969977/* Open a file with the specified flags (wrapper to open() function).
970978 Return a file descriptor on success. Set errno and return -1 on error.
971979
972- The file descriptor is created non-inheritable. */
980+ The file descriptor is created non-inheritable.
981+
982+ If interrupted by a signal, fail with EINTR. */
973983int
974984_Py_open_noraise (const char * pathname , int flags )
975985{
@@ -979,7 +989,9 @@ _Py_open_noraise(const char *pathname, int flags)
979989/* Open a file. Use _wfopen() on Windows, encode the path to the locale
980990 encoding and use fopen() otherwise.
981991
982- The file descriptor is created non-inheritable). */
992+ The file descriptor is created non-inheritable.
993+
994+ If interrupted by a signal, fail with EINTR. */
983995FILE *
984996_Py_wfopen (const wchar_t * path , const wchar_t * mode )
985997{
@@ -1012,7 +1024,9 @@ _Py_wfopen(const wchar_t *path, const wchar_t *mode)
10121024
10131025/* Wrapper to fopen().
10141026
1015- The file descriptor is created non-inheritable). */
1027+ The file descriptor is created non-inheritable.
1028+
1029+ If interrupted by a signal, fail with EINTR. */
10161030FILE *
10171031_Py_fopen (const char * pathname , const char * mode )
10181032{
@@ -1034,11 +1048,15 @@ _Py_fopen(const char *pathname, const char *mode)
10341048
10351049 The file descriptor is created non-inheritable.
10361050
1051+ When interrupted by a signal (open() fails with EINTR), retry the syscall,
1052+ except if the Python signal handler raises an exception.
1053+
10371054 The GIL must be held. */
10381055FILE *
10391056_Py_fopen_obj (PyObject * path , const char * mode )
10401057{
10411058 FILE * f ;
1059+ int async_err = 0 ;
10421060#ifdef MS_WINDOWS
10431061 wchar_t * wpath ;
10441062 wchar_t wmode [10 ];
@@ -1062,9 +1080,12 @@ _Py_fopen_obj(PyObject *path, const char *mode)
10621080 return NULL ;
10631081 }
10641082
1065- Py_BEGIN_ALLOW_THREADS
1066- f = _wfopen (wpath , wmode );
1067- Py_END_ALLOW_THREADS
1083+ do {
1084+ Py_BEGIN_ALLOW_THREADS
1085+ f = _wfopen (wpath , wmode );
1086+ Py_END_ALLOW_THREADS
1087+ } while (f == NULL
1088+ && errno == EINTR && !(async_err = PyErr_CheckSignals ()));
10681089#else
10691090 PyObject * bytes ;
10701091 char * path_bytes ;
@@ -1075,12 +1096,18 @@ _Py_fopen_obj(PyObject *path, const char *mode)
10751096 return NULL ;
10761097 path_bytes = PyBytes_AS_STRING (bytes );
10771098
1078- Py_BEGIN_ALLOW_THREADS
1079- f = fopen (path_bytes , mode );
1080- Py_END_ALLOW_THREADS
1099+ do {
1100+ Py_BEGIN_ALLOW_THREADS
1101+ f = fopen (path_bytes , mode );
1102+ Py_END_ALLOW_THREADS
1103+ } while (f == NULL
1104+ && errno == EINTR && !(async_err = PyErr_CheckSignals ()));
10811105
10821106 Py_DECREF (bytes );
10831107#endif
1108+ if (async_err )
1109+ return NULL ;
1110+
10841111 if (f == NULL ) {
10851112 PyErr_SetFromErrnoWithFilenameObject (PyExc_OSError , path );
10861113 return NULL ;
0 commit comments