Skip to content

Commit

Permalink
Merge pull request #3648 from willmmiles/json-response-locking
Browse files Browse the repository at this point in the history
Expand JSON buffer lock scope to entire web reply
  • Loading branch information
blazoncek authored Jan 6, 2024
2 parents 6ad4493 + 7711617 commit 801d92b
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 3 deletions.
16 changes: 16 additions & 0 deletions wled00/fcn_declare.h
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,22 @@ um_data_t* simulateSound(uint8_t simulationId);
void enumerateLedmaps();
uint8_t get_random_wheel_index(uint8_t pos);

// RAII guard class for the JSON Buffer lock
// Modeled after std::lock_guard
class JSONBufferGuard {
bool holding_lock;
public:
inline JSONBufferGuard(uint8_t module=255) : holding_lock(requestJSONBufferLock(module)) {};
inline ~JSONBufferGuard() { if (holding_lock) releaseJSONBufferLock(); };
inline JSONBufferGuard(const JSONBufferGuard&) = delete; // Noncopyable
inline JSONBufferGuard& operator=(const JSONBufferGuard&) = delete;
inline JSONBufferGuard(JSONBufferGuard&& r) : holding_lock(r.holding_lock) { r.holding_lock = false; }; // but movable
inline JSONBufferGuard& operator=(JSONBufferGuard&& r) { holding_lock |= r.holding_lock; r.holding_lock = false; return *this; };
inline bool owns_lock() const { return holding_lock; }
explicit inline operator bool() const { return owns_lock(); };
inline void release() { if (holding_lock) releaseJSONBufferLock(); holding_lock = false; }
};

#ifdef WLED_ADD_EEPROM_SUPPORT
//wled_eeprom.cpp
void applyMacro(byte index);
Expand Down
17 changes: 14 additions & 3 deletions wled00/json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -1050,12 +1061,13 @@ 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;
delete response;
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();

Expand Down Expand Up @@ -1098,7 +1110,6 @@ void serveJson(AsyncWebServerRequest* request)
DEBUG_PRINT(F("JSON content length: ")); DEBUG_PRINTLN(len);

request->send(response);
releaseJSONBufferLock();
servingClient = false;
}

Expand Down

0 comments on commit 801d92b

Please sign in to comment.