diff --git a/wled00/util.cpp b/wled00/util.cpp index 63e8b131..d9862bc7 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -222,17 +222,31 @@ bool isAsterisksOnly(const char* str, byte maxLen) //threading/network callback details: https://github.com/Aircoookie/WLED/pull/2336#discussion_r762276994 bool requestJSONBufferLock(uint8_t module) { - unsigned long now = millis(); + bool haveLock = false; + #ifdef ARDUINO_ARCH_ESP32 + // We use a recursive mutex to prevent parallel JSON writes from parallel tasks. + // This also fixes hanging up for the full timeout interval in cases when the contention is from the same task. + // see https://github.com/wled/WLED/pull/4089 for more details. + if (esp32SemTake(jsonBufferLockMutex, 1800) == pdTRUE) haveLock = true; // WLEDMM must wait longer than suspendStripService timeout = 1500ms + #else + // 8266: only wait in case that can_yield() tells us we can yield and delay + if (can_yield()) { + unsigned long now = millis(); + while (jsonBufferLock && millis()-now < 1800) delay(1); // wait for fraction for buffer lock // WLEDMM must wait longer than suspendStripService timeout = 1500ms + if (!jsonBufferLock) haveLock = true; + } + #endif - while (jsonBufferLock && millis()-now < 1100) delay(1); // wait for fraction for buffer lock - - if (jsonBufferLock) { + if (jsonBufferLock || !haveLock) { + if (haveLock) esp32SemGive(jsonBufferLockMutex); // we got the mutex, but jsonBufferLock says the opposite -> give up + delay(10); // WLEDMM experimental: small extra wait, in case that esp32 cores temporarily disagree on the value of jsonBufferLock USER_PRINT(F("ERROR: Locking JSON buffer failed! (still locked by ")); USER_PRINT(jsonBufferLock); USER_PRINTLN(")"); return false; // waiting time-outed } + // success - we keep holding the mutex until releaseJSONBufferLock() jsonBufferLock = module ? module : 255; DEBUG_PRINT(F("JSON buffer locked. (")); DEBUG_PRINT(jsonBufferLock); @@ -250,6 +264,7 @@ void releaseJSONBufferLock() DEBUG_PRINTLN(")"); fileDoc = nullptr; jsonBufferLock = 0; + esp32SemGive(jsonBufferLockMutex); // return the mutex }