@@ -16193,7 +16193,7 @@ typedef struct {
1619316193#ifdef HAVE_FDOPENDIR
1619416194 int fd ;
1619516195#endif
16196- _PyRecursiveMutex mutex ;
16196+ PyMutex mutex ;
1619716197} ScandirIterator ;
1619816198
1619916199#define ScandirIterator_CAST (op ) ((ScandirIterator *)(op))
@@ -16209,10 +16209,10 @@ ScandirIterator_is_closed(ScandirIterator *iterator)
1620916209static void
1621016210ScandirIterator_closedir (ScandirIterator * iterator )
1621116211{
16212- _PyRecursiveMutex_Lock (& iterator -> mutex );
16212+ PyMutex_Lock (& iterator -> mutex );
1621316213 HANDLE handle = iterator -> handle ;
1621416214 iterator -> handle = INVALID_HANDLE_VALUE ;
16215- _PyRecursiveMutex_Unlock (& iterator -> mutex );
16215+ PyMutex_Unlock (& iterator -> mutex );
1621616216
1621716217 if (handle == INVALID_HANDLE_VALUE ) {
1621816218 return ;
@@ -16223,46 +16223,56 @@ ScandirIterator_closedir(ScandirIterator *iterator)
1622316223 Py_END_ALLOW_THREADS
1622416224}
1622516225
16226+ static BOOL
16227+ ScandirIterator_nextdirentry (ScandirIterator * iterator , WIN32_FIND_DATAW * file_data )
16228+ {
16229+ BOOL has_error = FALSE;
16230+ BOOL has_result = FALSE;
16231+ PyMutex_Lock (& iterator -> mutex );
16232+ if (iterator -> handle != INVALID_HANDLE_VALUE ) {
16233+ if (iterator -> first_time ) {
16234+ has_result = TRUE;
16235+ memcpy (file_data , & iterator -> file_data , sizeof (WIN32_FIND_DATAW ));
16236+ iterator -> first_time = 0 ;
16237+ } else {
16238+ Py_BEGIN_ALLOW_THREADS
16239+ has_result = FindNextFileW (iterator -> handle , file_data );
16240+ Py_END_ALLOW_THREADS
16241+ has_error = !has_result && GetLastError () != ERROR_NO_MORE_FILES ;
16242+ }
16243+ }
16244+ PyMutex_Unlock (& iterator -> mutex );
16245+
16246+ /* Error or no more files */
16247+ if (has_error )
16248+ path_error (& iterator -> path );
16249+
16250+ return has_result ;
16251+ }
16252+
1622616253static PyObject *
1622716254ScandirIterator_iternext (PyObject * op )
1622816255{
1622916256 ScandirIterator * iterator = ScandirIterator_CAST (op );
16230- WIN32_FIND_DATAW * file_data = & iterator -> file_data ;
16231- BOOL success ;
16257+ WIN32_FIND_DATAW file_data ;
1623216258 PyObject * entry ;
1623316259
16234- _PyRecursiveMutex_Lock (& iterator -> mutex );
16235- while (iterator -> handle != INVALID_HANDLE_VALUE ) {
16236- if (!iterator -> first_time ) {
16237- Py_BEGIN_ALLOW_THREADS
16238- success = FindNextFileW (iterator -> handle , file_data );
16239- Py_END_ALLOW_THREADS
16240- if (!success ) {
16241- /* Error or no more files */
16242- if (GetLastError () != ERROR_NO_MORE_FILES )
16243- path_error (& iterator -> path );
16244- break ;
16245- }
16246- }
16247- iterator -> first_time = 0 ;
16248-
16260+ while (ScandirIterator_nextdirentry (iterator , & file_data )) {
1624916261 /* Skip over . and .. */
16250- if (wcscmp (file_data -> cFileName , L"." ) != 0 &&
16251- wcscmp (file_data -> cFileName , L".." ) != 0 )
16262+ if (wcscmp (file_data . cFileName , L"." ) != 0 &&
16263+ wcscmp (file_data . cFileName , L".." ) != 0 )
1625216264 {
1625316265 PyObject * module = PyType_GetModule (Py_TYPE (iterator ));
16254- entry = DirEntry_from_find_data (module , & iterator -> path , file_data );
16266+ entry = DirEntry_from_find_data (module , & iterator -> path , & file_data );
1625516267 if (!entry )
1625616268 break ;
16257- _PyRecursiveMutex_Unlock (& iterator -> mutex );
1625816269 return entry ;
1625916270 }
1626016271
1626116272 /* Loop till we get a non-dot directory or finish iterating */
1626216273 }
1626316274
1626416275 /* Already closed, error, or no more files */
16265- _PyRecursiveMutex_Unlock (& iterator -> mutex );
1626616276 ScandirIterator_closedir (iterator );
1626716277 return NULL ;
1626816278}
@@ -16278,10 +16288,10 @@ ScandirIterator_is_closed(ScandirIterator *iterator)
1627816288static void
1627916289ScandirIterator_closedir (ScandirIterator * iterator )
1628016290{
16281- _PyRecursiveMutex_Lock (& iterator -> mutex );
16291+ PyMutex_Lock (& iterator -> mutex );
1628216292 DIR * dirp = iterator -> dirp ;
1628316293 iterator -> dirp = NULL ;
16284- _PyRecursiveMutex_Unlock (& iterator -> mutex );
16294+ PyMutex_Unlock (& iterator -> mutex );
1628516295
1628616296 if (!dirp ) {
1628716297 return ;
@@ -16297,53 +16307,63 @@ ScandirIterator_closedir(ScandirIterator *iterator)
1629716307 return ;
1629816308}
1629916309
16310+ static int
16311+ ScandirIterator_nextdirentry (ScandirIterator * iterator , struct dirent * direntp )
16312+ {
16313+ int has_error = 0 ;
16314+ struct dirent * result = NULL ;
16315+ PyMutex_Lock (& iterator -> mutex );
16316+ if (iterator -> dirp ) {
16317+ errno = 0 ;
16318+ Py_BEGIN_ALLOW_THREADS
16319+ result = readdir (iterator -> dirp );
16320+ Py_END_ALLOW_THREADS
16321+ has_error = !result && errno != 0 ;
16322+ }
16323+ /* We need to make a copy of the result before releasing the lock */
16324+ if (result )
16325+ memcpy (direntp , result , sizeof (struct dirent ));
16326+ PyMutex_Unlock (& iterator -> mutex );
16327+
16328+ /* Error or no more files */
16329+ if (has_error )
16330+ path_error (& iterator -> path );
16331+
16332+ return result != NULL ;
16333+ }
16334+
1630016335static PyObject *
1630116336ScandirIterator_iternext (PyObject * op )
1630216337{
1630316338 ScandirIterator * iterator = ScandirIterator_CAST (op );
16304- struct dirent * direntp ;
16339+ struct dirent direntp ;
1630516340 Py_ssize_t name_len ;
1630616341 int is_dot ;
1630716342 PyObject * entry ;
1630816343
16309- _PyRecursiveMutex_Lock (& iterator -> mutex );
16310- while (iterator -> dirp ) {
16311- errno = 0 ;
16312- Py_BEGIN_ALLOW_THREADS
16313- direntp = readdir (iterator -> dirp );
16314- Py_END_ALLOW_THREADS
16315-
16316- if (!direntp ) {
16317- /* Error or no more files */
16318- if (errno != 0 )
16319- path_error (& iterator -> path );
16320- break ;
16321- }
16322-
16344+ while ((ScandirIterator_nextdirentry (iterator , & direntp ))) {
1632316345 /* Skip over . and .. */
16324- name_len = NAMLEN (direntp );
16325- is_dot = direntp -> d_name [0 ] == '.' &&
16326- (name_len == 1 || (direntp -> d_name [1 ] == '.' && name_len == 2 ));
16346+ name_len = NAMLEN (& direntp );
16347+ is_dot = direntp . d_name [0 ] == '.' &&
16348+ (name_len == 1 || (direntp . d_name [1 ] == '.' && name_len == 2 ));
1632716349 if (!is_dot ) {
1632816350 PyObject * module = PyType_GetModule (Py_TYPE (iterator ));
1632916351 entry = DirEntry_from_posix_info (module ,
16330- & iterator -> path , direntp -> d_name ,
16331- name_len , direntp -> d_ino
16352+ & iterator -> path , direntp . d_name ,
16353+ name_len , direntp . d_ino
1633216354#ifdef HAVE_DIRENT_D_TYPE
16333- , direntp -> d_type
16355+ , direntp . d_type
1633416356#endif
1633516357 );
1633616358 if (!entry )
1633716359 break ;
16338- _PyRecursiveMutex_Unlock (& iterator -> mutex );
1633916360 return entry ;
1634016361 }
1634116362
1634216363 /* Loop till we get a non-dot directory or finish iterating */
1634316364 }
1634416365
1634516366 /* Already closed, error, or no more files */
16346- _PyRecursiveMutex_Unlock (& iterator -> mutex );
1634716367 ScandirIterator_closedir (iterator );
1634816368 return NULL ;
1634916369}
@@ -16476,7 +16496,7 @@ os_scandir_impl(PyObject *module, path_t *path)
1647616496 if (!iterator )
1647716497 return NULL ;
1647816498
16479- iterator -> mutex = (_PyRecursiveMutex ){0 };
16499+ iterator -> mutex = (PyMutex ){0 };
1648016500#ifdef MS_WINDOWS
1648116501 iterator -> handle = INVALID_HANDLE_VALUE ;
1648216502#else
0 commit comments