ESPAsyncWebServer icon indicating copy to clipboard operation
ESPAsyncWebServer copied to clipboard

WHY I cannot have `delay()` or `yield()`?

Open MacDada opened this issue 1 year ago • 11 comments

server.on("/test", HTTP_GET, [](AsyncWebServerRequest *request) {
    // 1s OK, 3s crash -> when no wdtFeed
    auto seconds = 20;

    auto end = millis() + seconds * 1000;

    // this loop, when empty, causes a reboot after about 3 seconds
    // but imagine this is not an empty loop, but a real stuff that is just taking a bit of time…
    while (end > millis()) {
        //yield(); // panic, crash, restart
        //ESP.wdtFeed(); // no crashes even for long times, but everything else is being blocked
    }

    request->send(200, "text/plain", "It is OK :-)");
});

Hey, I'm trying to understand what's going on with the AsyncWebServer and delay() conflict. As you can see from the code:

  1. while (end > millis()) {} – empty not infinite loop causes a restart – I found out it is a Watchdog not being fed (it would be fed after every pass of the main loop, but ESPAsyncWerbServer runs "outside" of the main loop and actually blocks the main Arduino loop).

  2. while (end > millis()) { yield(); } – OK, so let's try to give a bit of time to the main Arduino's tasks that should be running in the background => nope, one cannot use yield() in the web controller. It causes a crash due to a panic.

  3. Same as above when using delay() – I discovered this issue while trying to do web controlled servo, with delay()s, ofc. Actually delay does yield inside, hence the problem.

  4. while (end > millis()) { ESP.wdtFeed(); } – OK, let's become a cheater and feed the dog within our delaying loop. It works! My device actually is waiting 20 seconds with no problem, and then giving the response back to the browser. Working like a charm. Almost… In the main Arduino loop I send information to the Serial every second – it is blocked until my web controller finishes.

Of course I read important things to remember, it is said what I should not use.

It is NOT said what should I use instead (I already know workarounds, like scheduling action for the main loop to actually do stuff).

It is not said WHY is that a problem.


So, after me wasting like 2 days trying to figure out what's going on [aka "learning the hard way"], I would like to ask:

  1. WHY does yield() in the web controller crash Arduino?
  2. Isn't it like hmm, dangerous (?) – the fact that even background Arduino stuff is being stopped while the web is being handled? Won't the WiFi connection drop? Or any other issue?
  3. I believe everything like that should be explained in the docs – am I missing something? I can make PR with docs update after I know it all [mind that I've started learning C++ like a month ago, if I were able to understand everything from analysing the source code, I would probably not be asking here…]

MacDada avatar Aug 03 '22 13:08 MacDada