diff --git a/wled00/util.cpp b/wled00/util.cpp index fc19d60bd..2e7056448 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -213,21 +213,33 @@ bool requestJSONBufferLock(uint8_t module) DEBUG_PRINTLN(F("ERROR: JSON buffer not allocated!")); return false; } - unsigned long now = millis(); - - while (jsonBufferLock && millis()-now < 250) delay(1); // wait for fraction for buffer lock +#if defined(ARDUINO_ARCH_ESP32) + // Use a recursive mutex type in case our task is the one holding the JSON buffer. + // This can happen during large JSON web transactions. In this case, we continue immediately + // and then will return out below if the lock is still held. + if (xSemaphoreTakeRecursive(jsonBufferLockMutex, 250) == pdFALSE) return false; // timed out waiting +#elif defined(ARDUINO_ARCH_ESP8266) + // If we're in system context, delay() won't return control to the user context, so there's + // no point in waiting. + if (can_yield()) { + unsigned long now = millis(); + while (jsonBufferLock && (millis()-now < 250)) delay(1); // wait for fraction for buffer lock + } +#else + #error Unsupported task framework - fix requestJSONBufferLock +#endif + // If the lock is still held - by us, or by another task if (jsonBufferLock) { - DEBUG_PRINT(F("ERROR: Locking JSON buffer failed! (still locked by ")); - DEBUG_PRINT(jsonBufferLock); - DEBUG_PRINTLN(")"); - return false; // waiting time-outed + DEBUG_PRINTF_P(PSTR("ERROR: Locking JSON buffer (%d) failed! (still locked by %d)\n"), module, jsonBufferLock); +#ifdef ARDUINO_ARCH_ESP32 + xSemaphoreGiveRecursive(jsonBufferLockMutex); +#endif + return false; } jsonBufferLock = module ? module : 255; - DEBUG_PRINT(F("JSON buffer locked. (")); - DEBUG_PRINT(jsonBufferLock); - DEBUG_PRINTLN(")"); + DEBUG_PRINTF_P(PSTR("JSON buffer locked. (%d)\n"), jsonBufferLock); pDoc->clear(); return true; } @@ -235,10 +247,11 @@ bool requestJSONBufferLock(uint8_t module) void releaseJSONBufferLock() { - DEBUG_PRINT(F("JSON buffer released. (")); - DEBUG_PRINT(jsonBufferLock); - DEBUG_PRINTLN(")"); + DEBUG_PRINTF_P(PSTR("JSON buffer released. (%d)\n"), jsonBufferLock); jsonBufferLock = 0; +#ifdef ARDUINO_ARCH_ESP32 + xSemaphoreGiveRecursive(jsonBufferLockMutex); +#endif } diff --git a/wled00/wled.h b/wled00/wled.h index f761b970d..d6915e7fb 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -810,6 +810,7 @@ WLED_GLOBAL int8_t spi_sclk _INIT(SPISCLKPIN); // global ArduinoJson buffer #if defined(ARDUINO_ARCH_ESP32) WLED_GLOBAL JsonDocument *pDoc _INIT(nullptr); +WLED_GLOBAL SemaphoreHandle_t jsonBufferLockMutex _INIT(xSemaphoreCreateRecursiveMutex()); #else WLED_GLOBAL StaticJsonDocument gDoc; WLED_GLOBAL JsonDocument *pDoc _INIT(&gDoc);