@@ -16181,6 +16181,7 @@ typedef struct {
1618116181#ifdef HAVE_FDOPENDIR
1618216182 int fd ;
1618316183#endif
16184+ PyMutex mutex ;
1618416185} ScandirIterator ;
1618516186
1618616187#define ScandirIterator_CAST (op ) ((ScandirIterator *)(op))
@@ -16190,18 +16191,21 @@ typedef struct {
1619016191static int
1619116192ScandirIterator_is_closed (ScandirIterator * iterator )
1619216193{
16193- return iterator -> handle == INVALID_HANDLE_VALUE ;
16194+ return _Py_atomic_load_ptr_relaxed ( & iterator -> handle ) == INVALID_HANDLE_VALUE ;
1619416195}
1619516196
1619616197static void
1619716198ScandirIterator_closedir (ScandirIterator * iterator )
1619816199{
16200+ PyMutex_Lock (& iterator -> mutex );
1619916201 HANDLE handle = iterator -> handle ;
16202+ iterator -> handle = INVALID_HANDLE_VALUE ;
16203+ PyMutex_Unlock (& iterator -> mutex );
1620016204
16201- if (handle == INVALID_HANDLE_VALUE )
16205+ if (handle == INVALID_HANDLE_VALUE ) {
1620216206 return ;
16207+ }
1620316208
16204- iterator -> handle = INVALID_HANDLE_VALUE ;
1620516209 Py_BEGIN_ALLOW_THREADS
1620616210 FindClose (handle );
1620716211 Py_END_ALLOW_THREADS
@@ -16215,11 +16219,8 @@ ScandirIterator_iternext(PyObject *op)
1621516219 BOOL success ;
1621616220 PyObject * entry ;
1621716221
16218- /* Happens if the iterator is iterated twice, or closed explicitly */
16219- if (iterator -> handle == INVALID_HANDLE_VALUE )
16220- return NULL ;
16221-
16222- while (1 ) {
16222+ PyMutex_Lock (& iterator -> mutex );
16223+ while (iterator -> handle != INVALID_HANDLE_VALUE ) {
1622316224 if (!iterator -> first_time ) {
1622416225 Py_BEGIN_ALLOW_THREADS
1622516226 success = FindNextFileW (iterator -> handle , file_data );
@@ -16241,13 +16242,15 @@ ScandirIterator_iternext(PyObject *op)
1624116242 entry = DirEntry_from_find_data (module , & iterator -> path , file_data );
1624216243 if (!entry )
1624316244 break ;
16245+ PyMutex_Unlock (& iterator -> mutex );
1624416246 return entry ;
1624516247 }
1624616248
1624716249 /* Loop till we get a non-dot directory or finish iterating */
1624816250 }
1624916251
16250- /* Error or no more files */
16252+ /* Already closed, error, or no more files */
16253+ PyMutex_Unlock (& iterator -> mutex );
1625116254 ScandirIterator_closedir (iterator );
1625216255 return NULL ;
1625316256}
@@ -16257,18 +16260,21 @@ ScandirIterator_iternext(PyObject *op)
1625716260static int
1625816261ScandirIterator_is_closed (ScandirIterator * iterator )
1625916262{
16260- return !iterator -> dirp ;
16263+ return !_Py_atomic_load_ptr_relaxed ( & iterator -> dirp ) ;
1626116264}
1626216265
1626316266static void
1626416267ScandirIterator_closedir (ScandirIterator * iterator )
1626516268{
16269+ PyMutex_Lock (& iterator -> mutex );
1626616270 DIR * dirp = iterator -> dirp ;
16271+ iterator -> dirp = NULL ;
16272+ PyMutex_Unlock (& iterator -> mutex );
1626716273
16268- if (!dirp )
16274+ if (!dirp ) {
1626916275 return ;
16276+ }
1627016277
16271- iterator -> dirp = NULL ;
1627216278 Py_BEGIN_ALLOW_THREADS
1627316279#ifdef HAVE_FDOPENDIR
1627416280 if (iterator -> path .fd != -1 )
@@ -16288,11 +16294,8 @@ ScandirIterator_iternext(PyObject *op)
1628816294 int is_dot ;
1628916295 PyObject * entry ;
1629016296
16291- /* Happens if the iterator is iterated twice, or closed explicitly */
16292- if (!iterator -> dirp )
16293- return NULL ;
16294-
16295- while (1 ) {
16297+ PyMutex_Lock (& iterator -> mutex );
16298+ while (iterator -> dirp ) {
1629616299 errno = 0 ;
1629716300 Py_BEGIN_ALLOW_THREADS
1629816301 direntp = readdir (iterator -> dirp );
@@ -16320,13 +16323,15 @@ ScandirIterator_iternext(PyObject *op)
1632016323 );
1632116324 if (!entry )
1632216325 break ;
16326+ PyMutex_Unlock (& iterator -> mutex );
1632316327 return entry ;
1632416328 }
1632516329
1632616330 /* Loop till we get a non-dot directory or finish iterating */
1632716331 }
1632816332
16329- /* Error or no more files */
16333+ /* Already closed, error, or no more files */
16334+ PyMutex_Unlock (& iterator -> mutex );
1633016335 ScandirIterator_closedir (iterator );
1633116336 return NULL ;
1633216337}
@@ -16459,6 +16464,7 @@ os_scandir_impl(PyObject *module, path_t *path)
1645916464 if (!iterator )
1646016465 return NULL ;
1646116466
16467+ iterator -> mutex = (PyMutex ){0 };
1646216468#ifdef MS_WINDOWS
1646316469 iterator -> handle = INVALID_HANDLE_VALUE ;
1646416470#else
0 commit comments