Skip to content

Commit d3076c4

Browse files
committed
use a mutex to make requestJSONBufferLock / releaseJSONBufferLock robust
similar to upstream wled#4089, but with slightly different "failure" logic.
1 parent 9b5ae9f commit d3076c4

File tree

1 file changed

+19
-4
lines changed

1 file changed

+19
-4
lines changed

wled00/util.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,17 +222,31 @@ bool isAsterisksOnly(const char* str, byte maxLen)
222222
//threading/network callback details: https://github.com/Aircoookie/WLED/pull/2336#discussion_r762276994
223223
bool requestJSONBufferLock(uint8_t module)
224224
{
225-
unsigned long now = millis();
226-
227-
while (jsonBufferLock && millis()-now < 1100) delay(1); // wait for fraction for buffer lock
225+
bool haveLock = false;
226+
#ifdef ARDUINO_ARCH_ESP32
227+
// We use a recursive mutex to prevent parallel JSON writes from parallel tasks.
228+
// This also fixes hanging up for the full timeout interval in cases when the contention is from the same task.
229+
// see https://github.com/wled/WLED/pull/4089 for more details.
230+
if (esp32SemTake(jsonBufferLockMutex, 1800) == pdTRUE) haveLock = true; // WLEDMM must wait longer than suspendStripService timeout = 1500ms
231+
#else
232+
// 8266: only wait in case that can_yield() tells us we can yield and delay
233+
if (can_yield()) {
234+
unsigned long now = millis();
235+
while (jsonBufferLock && millis()-now < 1800) delay(1); // wait for fraction for buffer lock // WLEDMM must wait longer than suspendStripService timeout = 1500ms
236+
if (!jsonBufferLock) haveLock = true;
237+
}
238+
#endif
228239

229-
if (jsonBufferLock) {
240+
if (jsonBufferLock || !haveLock) {
241+
if (haveLock) esp32SemGive(jsonBufferLockMutex); // we got the mutex, but jsonBufferLock says the opposite -> give up
242+
delay(10); // WLEDMM experimental: small extra wait, in case that esp32 cores temporarily disagree on the value of jsonBufferLock
230243
USER_PRINT(F("ERROR: Locking JSON buffer failed! (still locked by "));
231244
USER_PRINT(jsonBufferLock);
232245
USER_PRINTLN(")");
233246
return false; // waiting time-outed
234247
}
235248

249+
// success - we keep holding the mutex until releaseJSONBufferLock()
236250
jsonBufferLock = module ? module : 255;
237251
DEBUG_PRINT(F("JSON buffer locked. ("));
238252
DEBUG_PRINT(jsonBufferLock);
@@ -250,6 +264,7 @@ void releaseJSONBufferLock()
250264
DEBUG_PRINTLN(")");
251265
fileDoc = nullptr;
252266
jsonBufferLock = 0;
267+
esp32SemGive(jsonBufferLockMutex); // return the mutex
253268
}
254269

255270

0 commit comments

Comments
 (0)