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
This commit is contained in:
Will Miles 2024-01-06 10:09:07 -05:00
parent 6382d2b730
commit 9d3c0f4ff0

View File

@ -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; static volatile bool servingClient = false;
void serveJson(AsyncWebServerRequest* request) void serveJson(AsyncWebServerRequest* request)
{ {
@ -1050,12 +1061,12 @@ void serveJson(AsyncWebServerRequest* request)
return; 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); serveJsonError(request, 503, ERR_NOBUF);
servingClient = false; servingClient = false;
return; 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(); JsonVariant lDoc = response->getRoot();
@ -1098,7 +1109,6 @@ void serveJson(AsyncWebServerRequest* request)
DEBUG_PRINT(F("JSON content length: ")); DEBUG_PRINTLN(len); DEBUG_PRINT(F("JSON content length: ")); DEBUG_PRINTLN(len);
request->send(response); request->send(response);
releaseJSONBufferLock();
servingClient = false; servingClient = false;
} }