Skip to content

Commit

Permalink
Prevent JSON buffer clear after failed lock attempt
Browse files Browse the repository at this point in the history
(alternative to Aircoookie#3743)
  • Loading branch information
blazoncek committed Feb 7, 2024
1 parent e165838 commit 6dcd959
Showing 1 changed file with 13 additions and 11 deletions.
24 changes: 13 additions & 11 deletions wled00/json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1030,17 +1030,18 @@ void serializeModeNames(JsonArray arr)
}
}


// Global buffer locking response helper class
class GlobalBufferAsyncJsonResponse: public JSONBufferGuard, public AsyncJsonResponse {
// Global buffer locking response helper class (to make sure lock is released when AsyncJsonResponse is destroyed)
class LockedJsonResponse: public AsyncJsonResponse {
public:
inline GlobalBufferAsyncJsonResponse(bool isArray) : JSONBufferGuard(17), AsyncJsonResponse(pDoc, isArray) {};
virtual ~GlobalBufferAsyncJsonResponse() {};

// Other members are inherited
// WARNING: constructor assumes requestJSONBufferLock() was successfully acquired externally/prior to constructing the instance
// Not a good practice with C++. Unfortunately AsyncJsonResponse only has 2 constructors - for dynamic buffer or existing buffer,
// with existing buffer it clears its content during construction
// if the lock was not acquired (using JSONBufferGuard class) previous implementation still cleared existing buffer
inline LockedJsonResponse(JsonDocument *doc, bool isArray) : AsyncJsonResponse(doc, isArray) {};
// destructor will remove JSON buffer lock when response is destroyed in AsyncWebServer
virtual ~LockedJsonResponse() { releaseJSONBufferLock(); };
};


void serveJson(AsyncWebServerRequest* request)
{
byte subJson = 0;
Expand Down Expand Up @@ -1071,12 +1072,13 @@ void serveJson(AsyncWebServerRequest* request)
return;
}

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()) {
if (!requestJSONBufferLock(17)) {
serveJsonError(request, 503, ERR_NOBUF);
delete response;
return;
}
// releaseJSONBufferLock() will be called when "response" is destroyed (from AsyncWebServer)
// make sure you delete "response" if no "request->send(response);" is made
LockedJsonResponse *response = new LockedJsonResponse(pDoc, subJson==JSON_PATH_FXDATA || subJson==JSON_PATH_EFFECTS); // will clear and convert JsonDocument into JsonArray if necessary

JsonVariant lDoc = response->getRoot();

Expand Down

0 comments on commit 6dcd959

Please sign in to comment.