@@ -16181,6 +16181,7 @@ typedef struct {
16181
16181
#ifdef HAVE_FDOPENDIR
16182
16182
int fd ;
16183
16183
#endif
16184
+ PyMutex mutex ;
16184
16185
} ScandirIterator ;
16185
16186
16186
16187
#define ScandirIterator_CAST (op ) ((ScandirIterator *)(op))
@@ -16190,18 +16191,21 @@ typedef struct {
16190
16191
static int
16191
16192
ScandirIterator_is_closed (ScandirIterator * iterator )
16192
16193
{
16193
- return iterator -> handle == INVALID_HANDLE_VALUE ;
16194
+ return _Py_atomic_load_ptr_relaxed ( & iterator -> handle ) == INVALID_HANDLE_VALUE ;
16194
16195
}
16195
16196
16196
16197
static void
16197
16198
ScandirIterator_closedir (ScandirIterator * iterator )
16198
16199
{
16200
+ PyMutex_Lock (& iterator -> mutex );
16199
16201
HANDLE handle = iterator -> handle ;
16202
+ iterator -> handle = INVALID_HANDLE_VALUE ;
16203
+ PyMutex_Unlock (& iterator -> mutex );
16200
16204
16201
- if (handle == INVALID_HANDLE_VALUE )
16205
+ if (handle == INVALID_HANDLE_VALUE ) {
16202
16206
return ;
16207
+ }
16203
16208
16204
- iterator -> handle = INVALID_HANDLE_VALUE ;
16205
16209
Py_BEGIN_ALLOW_THREADS
16206
16210
FindClose (handle );
16207
16211
Py_END_ALLOW_THREADS
@@ -16215,11 +16219,8 @@ ScandirIterator_iternext(PyObject *op)
16215
16219
BOOL success ;
16216
16220
PyObject * entry ;
16217
16221
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 ) {
16223
16224
if (!iterator -> first_time ) {
16224
16225
Py_BEGIN_ALLOW_THREADS
16225
16226
success = FindNextFileW (iterator -> handle , file_data );
@@ -16241,13 +16242,15 @@ ScandirIterator_iternext(PyObject *op)
16241
16242
entry = DirEntry_from_find_data (module , & iterator -> path , file_data );
16242
16243
if (!entry )
16243
16244
break ;
16245
+ PyMutex_Unlock (& iterator -> mutex );
16244
16246
return entry ;
16245
16247
}
16246
16248
16247
16249
/* Loop till we get a non-dot directory or finish iterating */
16248
16250
}
16249
16251
16250
- /* Error or no more files */
16252
+ /* Already closed, error, or no more files */
16253
+ PyMutex_Unlock (& iterator -> mutex );
16251
16254
ScandirIterator_closedir (iterator );
16252
16255
return NULL ;
16253
16256
}
@@ -16257,18 +16260,21 @@ ScandirIterator_iternext(PyObject *op)
16257
16260
static int
16258
16261
ScandirIterator_is_closed (ScandirIterator * iterator )
16259
16262
{
16260
- return !iterator -> dirp ;
16263
+ return !_Py_atomic_load_ptr_relaxed ( & iterator -> dirp ) ;
16261
16264
}
16262
16265
16263
16266
static void
16264
16267
ScandirIterator_closedir (ScandirIterator * iterator )
16265
16268
{
16269
+ PyMutex_Lock (& iterator -> mutex );
16266
16270
DIR * dirp = iterator -> dirp ;
16271
+ iterator -> dirp = NULL ;
16272
+ PyMutex_Unlock (& iterator -> mutex );
16267
16273
16268
- if (!dirp )
16274
+ if (!dirp ) {
16269
16275
return ;
16276
+ }
16270
16277
16271
- iterator -> dirp = NULL ;
16272
16278
Py_BEGIN_ALLOW_THREADS
16273
16279
#ifdef HAVE_FDOPENDIR
16274
16280
if (iterator -> path .fd != -1 )
@@ -16288,11 +16294,8 @@ ScandirIterator_iternext(PyObject *op)
16288
16294
int is_dot ;
16289
16295
PyObject * entry ;
16290
16296
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 ) {
16296
16299
errno = 0 ;
16297
16300
Py_BEGIN_ALLOW_THREADS
16298
16301
direntp = readdir (iterator -> dirp );
@@ -16320,13 +16323,15 @@ ScandirIterator_iternext(PyObject *op)
16320
16323
);
16321
16324
if (!entry )
16322
16325
break ;
16326
+ PyMutex_Unlock (& iterator -> mutex );
16323
16327
return entry ;
16324
16328
}
16325
16329
16326
16330
/* Loop till we get a non-dot directory or finish iterating */
16327
16331
}
16328
16332
16329
- /* Error or no more files */
16333
+ /* Already closed, error, or no more files */
16334
+ PyMutex_Unlock (& iterator -> mutex );
16330
16335
ScandirIterator_closedir (iterator );
16331
16336
return NULL ;
16332
16337
}
@@ -16459,6 +16464,7 @@ os_scandir_impl(PyObject *module, path_t *path)
16459
16464
if (!iterator )
16460
16465
return NULL ;
16461
16466
16467
+ iterator -> mutex = (PyMutex ){0 };
16462
16468
#ifdef MS_WINDOWS
16463
16469
iterator -> handle = INVALID_HANDLE_VALUE ;
16464
16470
#else
0 commit comments