mirror of
https://github.com/micropython/micropython.git
synced 2026-01-06 12:10:13 +01:00
extmod/vfs: Add finaliser to ilistdir to close directory handle.
When iterating over filesystem/folders with os.iterdir(), an open file (directory) handle is used internally. Currently this file handle is only closed once the iterator is completely drained, eg. once all entries have been looped over / converted into list etc. If a program opens an iterdir but does not loop over it, or starts to loop over the iterator but breaks out of the loop, then the handle never gets closed. In this state, when the iter object is cleaned up by the garbage collector this open handle can cause corruption of the filesystem. Fixes issues #6568 and #8506.
This commit is contained in:
committed by
Damien George
parent
582b3e4e78
commit
4e0964b59f
@@ -28,6 +28,10 @@
|
||||
#include "py/mpconfig.h"
|
||||
#if MICROPY_VFS_FAT
|
||||
|
||||
#if !MICROPY_ENABLE_FINALISER
|
||||
#error "MICROPY_VFS_FAT requires MICROPY_ENABLE_FINALISER"
|
||||
#endif
|
||||
|
||||
#if !MICROPY_VFS
|
||||
#error "with MICROPY_VFS_FAT enabled, must also enable MICROPY_VFS"
|
||||
#endif
|
||||
@@ -118,6 +122,7 @@ STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(fat_vfs_mkfs_obj, MP_ROM_PTR(&fat_vfs_mk
|
||||
typedef struct _mp_vfs_fat_ilistdir_it_t {
|
||||
mp_obj_base_t base;
|
||||
mp_fun_1_t iternext;
|
||||
mp_fun_1_t finaliser;
|
||||
bool is_str;
|
||||
FF_DIR dir;
|
||||
} mp_vfs_fat_ilistdir_it_t;
|
||||
@@ -162,6 +167,13 @@ STATIC mp_obj_t mp_vfs_fat_ilistdir_it_iternext(mp_obj_t self_in) {
|
||||
return MP_OBJ_STOP_ITERATION;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mp_vfs_fat_ilistdir_it_del(mp_obj_t self_in) {
|
||||
mp_vfs_fat_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
// ignore result / error because we may be closing a second time.
|
||||
f_closedir(&self->dir);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
bool is_str_type = true;
|
||||
@@ -176,8 +188,10 @@ STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) {
|
||||
}
|
||||
|
||||
// Create a new iterator object to list the dir
|
||||
mp_vfs_fat_ilistdir_it_t *iter = mp_obj_malloc(mp_vfs_fat_ilistdir_it_t, &mp_type_polymorph_iter);
|
||||
mp_vfs_fat_ilistdir_it_t *iter = m_new_obj_with_finaliser(mp_vfs_fat_ilistdir_it_t);
|
||||
iter->base.type = &mp_type_polymorph_iter_with_finaliser;
|
||||
iter->iternext = mp_vfs_fat_ilistdir_it_iternext;
|
||||
iter->finaliser = mp_vfs_fat_ilistdir_it_del;
|
||||
iter->is_str = is_str_type;
|
||||
FRESULT res = f_opendir(&self->fatfs, &iter->dir, path);
|
||||
if (res != FR_OK) {
|
||||
|
||||
Reference in New Issue
Block a user