From 9d3c0f4ff082d7f596c142e32e42eda607d6c1ae Mon Sep 17 00:00:00 2001 From: Will Miles Date: Sat, 6 Jan 2024 10:09:07 -0500 Subject: [PATCH] serveJson: Ensure semaphore scope lasts until reply is done Extend the JSON response class to hold the global JSON buffer lock until the transaction is completed. Fixes #3641 --- wled00/json.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/wled00/json.cpp b/wled00/json.cpp index ef2bdf346..d9bbb74ce 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -1009,6 +1009,17 @@ void serializeModeNames(JsonArray arr) } } + +// Global buffer locking response helper class +class GlobalBufferAsyncJsonResponse: public JSONBufferGuard, public AsyncJsonResponse { + public: + inline GlobalBufferAsyncJsonResponse(bool isArray) : JSONBufferGuard(17), AsyncJsonResponse(pDoc, isArray) {}; + virtual ~GlobalBufferAsyncJsonResponse() {}; + + // Other members are inherited +}; + + static volatile bool servingClient = false; void serveJson(AsyncWebServerRequest* request) { @@ -1050,12 +1061,12 @@ void serveJson(AsyncWebServerRequest* request) return; } - if (!requestJSONBufferLock(17)) { + GlobalBufferAsyncJsonResponse *response = new GlobalBufferAsyncJsonResponse(subJson==JSON_PATH_FXDATA || subJson==JSON_PATH_EFFECTS); // will clear and convert JsonDocument into JsonArray if necessary + if (!response->owns_lock()) { serveJsonError(request, 503, ERR_NOBUF); servingClient = false; return; } - AsyncJsonResponse *response = new AsyncJsonResponse(pDoc, subJson==JSON_PATH_FXDATA || subJson==JSON_PATH_EFFECTS); // will clear and convert JsonDocument into JsonArray if necessary JsonVariant lDoc = response->getRoot(); @@ -1098,7 +1109,6 @@ void serveJson(AsyncWebServerRequest* request) DEBUG_PRINT(F("JSON content length: ")); DEBUG_PRINTLN(len); request->send(response); - releaseJSONBufferLock(); servingClient = false; }