-
-
Notifications
You must be signed in to change notification settings - Fork 564
bump ESPAsyncWebServer to v3.7.6 #2633
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
plieven
commented
Apr 8, 2025
- dynamically adjust prometheus endpoint response buffer size
src/WebApi_prometheus.cpp
Outdated
| stream->addHeader("Cache-Control", "no-cache"); | ||
| if (stream->available() > initialResponseBufferSize) { | ||
| initialResponseBufferSize = stream->available(); | ||
| MessageOutput.printf("Increased /api/prometheus/metrics initialResponseBufferSize to %u bytes\r\n", initialResponseBufferSize); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please use PRIu32 instead of %u? Otherwise we might have problems when migrating to newer gcc versions. (and force push)
e.g.
MessageOutput.printf("Increased /api/prometheus/metrics initialResponseBufferSize to %" PRId32 " bytes\r\n", initialResponseBufferSize);
d700e54 to
b5f723a
Compare
|
fixed, I should have known better ... |
|
Thank you. I've merged it into my local dev branch, and will release a new version tomorrow. |
|
I see a I am pretty sure that's new. |
|
Thats interessting..... I output AsyncResponseStream::AsyncResponseStream(const char *contentType, size_t bufferSize) {
_code = 200;
_contentLength = 0;
_contentType = contentType;
// internal buffer will be null on allocation failure
_content = std::unique_ptr<cbuf>(new cbuf(bufferSize));
if (_content->size() != bufferSize) {
#ifdef ESP32
log_e("Failed to allocate %u", _content->size());
#endif
}
}@mathieucarbou is there maybe something wrong with size vs. index? |
|
@mathieucarbou i think the check in ESPAsyncWebserver is wrong. I guess cbuf allocates an extra byte for a terminating \0.
That check should be >= and not ==.
|
|
I think I found the reason... cbuf::cbuf(size_t size) :
next(NULL), _size(size+1), _buf(new char[size+1]), _bufend(_buf + size + 1), _begin(_buf), _end(_begin)
{
}
size_t cbuf::size()
{
return _size;
}They are allocating And I think |
|
crap! |
|
Why I didn't get the warning when I run my MRE ? |
|
@tbnobody : weird, I do not have the same cbuf impl. as you 🤯 I do not have the extra character. the one I have , which works: cbuf::cbuf(size_t size) : next(NULL), has_peek(false), peek_byte(0), _buf(xRingbufferCreate(size, RINGBUF_TYPE_BYTEBUF)) {
if (_buf == NULL) {
log_e("failed to allocate ring buffer");
}
CBUF_MUTEX_CREATE();
}Oh... ! |
More like |
Yes, I replied via e-mail and haven't checked the source... The change you propose should work with both core versions. Just to be 100% sure if the initial allocation fails, cbuf isn't NULL or is it? |
thats only visible on the serial console, right? I only checked the webconsole though. |
cbuf cannot be null: it is not a On Arduino Core 3, not likely because the call to On Arduino Core 2, there is a new chat[] in the ctor, so the ctor will crahs the board on a failed allocation because of the usage of OpenDTU should switch to Arduino Core 3 with pioarduino:
|
that's because of the arduino core 2 implementation not returning the same size as arduino core 3 implementation. this is just an annoying error log: the cbuf is allocated behind. |
|
Okay, understood. In Core 2 it will crash, but in Core 3 the buffer can be up to 3 bytes larger as @tbnobody mentioned from the docs. So we need the modified check? |
Yes and no, the code he mentioned is arduino core 2 code. the cbuf implementation in arduino core 3 is using a ring buffer and the size matches the requested size. The hack with the added byte is only in core 2 it seems.
|
|
okay, what are the official requirements for ESPAsyncWebServer? If you allow arduino core 2, you should fix that bogus error message. While looking at WebResponses.cpp I checked what happens in AsyncResponseStream::write if the cbuf::resize fails. It will return the orignal size. We do not detect this and just overwrite contents of the ring buffer if it wraps. Do not know what the right behaviour is. return 0 and do nothing, return the requested write size and do nothring or overwrite... |
We support latest released versions of Arduino Core 2 and 3, but we strongly advise to use 3 because at one point we won't be able to keep 2 compatibility. Arduino Core team does not maintain 2 anymore: this is a EOL version. Everybody should switch to 3 now.... |
|
I have a PR ready that is building and will release a v3.7.6 in a few minutes: ESP32Async/ESPAsyncWebServer#152 |
Yeah, the commit creeped in the conversation so I missed it. |
Oh !!! Yes that should be fixed... No overwrite should happen. Is it on Arduino core 2 ? |
|
@mathieucarbou v2 and v3 are in agreement on that: |
|
Fortunately both implementations clamp the write size to the buffer size:
`size_t size_to_write = (size < bytes_available) ? size : bytes_available;`
|
|
Added a commit to log also the failed re-allocations: ESP32Async/ESPAsyncWebServer@bf9f457 |
after OpenDTU v24.9.30 was released there was a subtle change in the ESPAsyncWebServer which changed the internal data structure for AsyncResponseStream from cbuf to StringStream. This introduced WDT resets when scraping at least the prometheus API endpoint [1]. ESPAsyncWebServer v3.7.6 addresses this issue by reverting the data structure back to cbuf. [1] tbnobody#2535 Signed-off-by: Peter Lieven <[email protected]>
…buffer size the current implementation allocates a 40kB buffer right from the start. In most cases this is way too big. This patch dynamically learns the right required size for the local setup and preallocates just as much space as needed. Signed-off-by: Peter Lieven <[email protected]>
b5f723a to
e6e1f3a
Compare
|
@tbnobody updated the PR to include ESPAsyncWebServer v3.7.6. The arduino core update to v3 is a different thing that should be thoughtfully tested. |
|
@mathieucarbou just a question that was not trivial to answer for me because I am not that familiar with the ESPAsyncWebServer code. If I use a AsyncJsonResponse does it interally use an AsyncStreamResponse at some point? Becuase other users that are not using prometheus reported that they can trigger the ESP resets by subsequently calling API endpoints like /api/system/status which internally all use AsyncJsonResponse. |
The ChunkPrint is a hack to skip the first bytes if _fillBuffer is called again (which triggers a new json serialization). What I do not understand though in this code is why len is returned instead of |
Have merged it into my local dev branch. Works great and fast.. Will keep it running tomorrow during the day and release a new version at evening.. And yes, core v3 is a complete different topic. Some parts don't even compile at the moment (W5500 driver) some parts are already fixed.. But the biggest problem is the additional flash usage. currently 89% flash are used.. with core 3 it's 97%. |
You should look at https://github.com/mathieucarbou/MycilaSafeBoot. It allows having a bootable recovery partition used specifically for updates (which is then small), and a > 3MB partition size for the app. I am using MycilaESPConnect for network manager, but you could easily reproduce the same mechanism by reloading the network info from safeboot so that it keeps same AP name / IP / etc. This dual-partition system largely used to facilitate OTA is a waste of space. Nearly half of the space is always unused. |
|
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new discussion or issue for related concerns. |