AsyncWebServer_Teensy41 mutex protection needed?

Hello all,

I've got a project in progress and have been using the
AsyncWebServer_Teensy41 with a fair amount of success. One thing has been worrying me, though.

I have a process that is generating data on a timer, then when a web client causes a callback to the function I've registered with server.on(), I populate it with the data. I'm concerned about the underpinnings of the callback: Is that happening as an interrupt from the lwip code? Do I need to protect it with a mutex?

I'm not using threads, just your bog-standard setup and loop, along with a nice little timer functionality.

... and by "Do I need to protect it with a mutex" I mean protect my populating of the data array.

I've looked over the documentation for AsyncWebServer_Teensy41 and it appears to be copy-paste from the original ESP32-based developer. It really doesn't go into this kind of detail there either. The problem is more troublesome because this code is based on these:
  • khoih-prog/Teensy41_AsyncTCP
  • ssilverman/QNEthernet
So I'm not sure where to look to get to the bottom of this. Is this all called round-robin (cooperatively) or are the Async server call backs sourced from an ethernet interrupt?

Here's how that server library is using the QNEthenet library: It uses the initialization code and the Ethernet ISR, but nothing else. It uses the lwIP API, otherwise, for its entire function (a slightly-modified copy is included with QNEthernet).

Now, because the QNEthernet library is being used to shepherd packets, the server library uses whatever happens under the covers to convey those packets. In this case, when packets arrive, they trigger the Ethernet ISR and an atomic flag is set. Sometime later, those packets are picked up in a non-ISR context (by looking at that atomic flag) and relayed to the lwIP stack. I think it's likely that that server library receives packets in a non-ISR context too. Everything in QNEthernet happens from an Ethernet.loop() (where that flag is ultimately checked) which is configured to run every time the main program loop() ends (yield() is called at this point by the system), or every time your own code calls yield() or, for example, delay().
This explains a lot. I did some coding experiments where I incremented a variable an even number of times in the main loop, then tried to protect it with various interrupt/noInterrupt calls, delays, yield(), and other interstitial function calls. Then I looked at my browser to see if I ever got odd numbers that would suggest the page was getting served between the two increments. The results really didn't make any sense to me.

Your explanation that the Ethernet.loop() is called at the bottom of the main program loop, during a delay(), or during a yield() really clears this up.

Many thanks for your answer and for your work on making PlatformIO pretty darned impressive!
You’re welcome. I cannot claim much PlatformIO work, however, other than some how-to posts about it and an EHEX PR in their repo. :) I did write the QNEthernet library, however.