Trying to serve small webapp results in "vfs_fat: open: no free file descriptors"
Posted: Tue Oct 05, 2021 7:36 pm
I have a small webapp I've developed in HTML and JavaScript that is stored on a microSD card. I'm using the ESPAsyncWebServer to serve this up from an ESP32-CAM. It's a single HTML page with a JavaScript date/time picker. This had been working perfectly with my iPhone, but trying it today (after updating my iPhone to iOS 15) the page doesn't load correctly and the ESP32 is writing to the serial terminal:
12:08:21.390 -> E (238446) vfs_fat: open: no free file descriptors
Sometimes I'll see multiple of these messages and it corresponds to various .js files not loading in the client. I've connected my iPhone to my iMac and used the debugging feature built into Safari to verify that the iPhone is not being served these files.
I have used both the SD and SD_MMC libraries for accessing the files and they behave identically.
What I think is happening is that the iPhone is requesting the files in parallel from the Async web server. If I move to the edge of the wifi connection to the ESP32 it seems that things slow down enough that the entire page loads correctly. Coming back to where there is a strong wifi connection to the ESP32 breaks the page again and I see the "no free file descriptors" message in the serial console again.
I don't need this to be a high performance webserver. It would be fine to serve one file at a time if that's what it took to get all of the files served to the client. I'd appreciate any help you can provide.
Attached is a small program that will create a Wifi access point, start up the webserver, and serve static files from the SD card of an ESP32-CAM.
12:08:21.390 -> E (238446) vfs_fat: open: no free file descriptors
Sometimes I'll see multiple of these messages and it corresponds to various .js files not loading in the client. I've connected my iPhone to my iMac and used the debugging feature built into Safari to verify that the iPhone is not being served these files.
I have used both the SD and SD_MMC libraries for accessing the files and they behave identically.
What I think is happening is that the iPhone is requesting the files in parallel from the Async web server. If I move to the edge of the wifi connection to the ESP32 it seems that things slow down enough that the entire page loads correctly. Coming back to where there is a strong wifi connection to the ESP32 breaks the page again and I see the "no free file descriptors" message in the serial console again.
I don't need this to be a high performance webserver. It would be fine to serve one file at a time if that's what it took to get all of the files served to the client. I'd appreciate any help you can provide.
Attached is a small program that will create a Wifi access point, start up the webserver, and serve static files from the SD card of an ESP32-CAM.
Code: Select all
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncEventSource.h>
#include <WebAuthentication.h>
#include <AsyncWebSocket.h>
#include <StringArray.h>
#include <AsyncJson.h>
#include <AsyncWebSynchronization.h>
#include <WebHandlerImpl.h>
#include <WebResponseImpl.h>
#include "FS.h"
#include "SD.h"
#include "SPI.h"
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
// Set your access point network credentials
const char* ssid = "network name";
const char* password = "passwordgoeshere";
void initSDCard(){
Serial.begin(115200);
delay(1000);
SPI.begin(14, 2, 15, 13);
if(!SD.begin(13)) {
Serial.println("SD Card: mounting failed.");
} else {
Serial.println("SD Card: mounted.");
}
uint8_t cardType = SD.cardType();
if(cardType == CARD_NONE){
Serial.println("No SD card attached");
return;
}
Serial.print("SD Card Type: ");
if(cardType == CARD_MMC){
Serial.println("MMC");
} else if(cardType == CARD_SD){
Serial.println("SDSC");
} else if(cardType == CARD_SDHC){
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
Serial.printf("SD Card Size: %lluMB\n", cardSize);
}
void setup() {
// put your setup code here, to run once:
initSDCard();
// Setting the ESP as an access point
Serial.print("Starting AP...");
// Remove the password parameter, if you want the AP to be open
WiFi.softAP(ssid, password);
IPAddress IP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(IP);
server.serveStatic("/", SD, "/");
server.begin();
}
void loop() {
// put your main code here, to run repeatedly:
}