lorol / LITTLEFS

LittleFS library for arduino-esp32
GNU General Public License v2.0
167 stars 68 forks source link

LittleFS has a multithreading problem in esp_littlefs_info #44

Open tbaust opened 2 years ago

tbaust commented 2 years ago

I have a small project which uses the LittleFS in a multithreaded environment (RTOS tasks with a custom ESP32 WROOM board). One of the threads is using "ESP Async WebServer" and sometimes (every fourth or fifth attempt) it returns "Error 500" because (seen at serial log).

.pio\libdeps\esp32dev\LittleFS_esp32\src\lfs.c:1076:error: Corrupted dir pair at {0x20, 0x1f} [E][vfs_api.cpp:64] open(): /littlefs/www/favicon.ico does not exist .pio\libdeps\esp32dev\LittleFS_esp32\src\lfs.c:1076:error: Corrupted dir pair at {0x0, 0x1} [E][vfs_api.cpp:64] open(): /littlefs/www/config.htm does not exist .pio\libdeps\esp32dev\LittleFS_esp32\src\lfs.c:1076:error: Corrupted dir pair at {0x20, 0x1f} ...

and yes the above files exists and after the next attempt (just reload in Chrome) it works also again (it's sporadic failing).

A second thread publishes some data to the MQTT server in regular intervals (also the currently used size of the filesystem - so FS.usedBytes() gets called). After I disable this call it works perfectly and no FS errors are there.

...after I added a sem_take/sem_give at esp_littlefs.c esp_littlefs_info it works so please include the fix in your repository :-)

zekageri commented 2 years ago

I just encountered this issue.

I tried to create a performance monitor class which would periodically asks the file system and other components about their states.

Like the file system for it's usedBytes and things like that. My app started crashing all over the place and i could not upload a file to my flash via http file upload when this reading happened.

Bad blocks started to happen all over the place, i had to erase my flash and reupload all over again. I commented out my periodic reading function and everything works fine.

That was basically this:

void P_Monitor::readResources() {
    if(!reading){
        heapSize = ESP.getHeapSize();
        freeHeap = ESP.getFreeHeap();
        usedHeap = heapSize - freeHeap;

        psRamSize = ESP.getPsramSize();
        freePSRam = ESP.getFreePsram();
        usedPSRam = psRamSize - freePSRam;

        totalFS = LITTLEFS.totalBytes();
        usedFS  = LITTLEFS.usedBytes();
        freeFS  = totalFS - usedFS;
        Serial.printf("Free heap: %d byte\r\n", freeHeap);
        /*
        timeTaskStack       = uxTaskGetStackHighWaterMark(espTimeTask_Handle);
        fileSystemTaskStack = uxTaskGetStackHighWaterMark(fileSystemTask_Handle);
        mBusTaskStack       = uxTaskGetStackHighWaterMark(modBusTask_Handle);
        thermTaskStack      = uxTaskGetStackHighWaterMark(thermTask_Handle);
        shutdownTaskStack   = uxTaskGetStackHighWaterMark(shutTask_Handle);
        */
    }
}

void P_Monitor::handleLookup() {
    // 1 sec interval
    if (millis() - lastLookUpMs > lookupFreqMs) {
        lastLookUpMs = millis();
        //readResources();
    }
}

I assume this is because LITTLEFS does not implement semaphore or any other safety mechanism into it. If i create a class for the file system manipulations i can avoid crash on my own writes / reads with a semaphore but what if i use a webserver library for example ESPAsyncWebserver which uses it's own functions. If i load a page with the server library it could crash too if another part of my program reading or writing to the flash with LITTLEFS.

Where did you put your semaphore in esp_littlefs.c ?

tbaust commented 2 years ago

Just have a look at my pull request/fork this fixed it for me

simap commented 2 years ago

I can confirm the fix in https://github.com/lorol/LITTLEFS/pull/45 resolved a similar issue for me.