fix(displayidle): avoid LVGL->MCP lock inversion that could freeze RLCD

Read MCP override state outside LVGL lock in tick().
Previously: LVGL lock -> MCP mutex (tick) vs MCP mutex -> LVGL lock (video task startMcpScreensaver) = deadlock risk observed on RLCD when text tool called.
Now: MCP state read first, then LVGL lock. Preserves <1s flash guard (isMcpActive).

Board: waveshare-esp32-s3-rlcd 0x2b78b0 32%% free, flashed to /dev/cu.usbmodem101

Co-Authored-By: internal-model
This commit is contained in:
Adolfo Reyna
2026-07-11 21:32:11 -04:00
parent 6235fa0541
commit 3629ffef2c
@@ -147,6 +147,16 @@ void DisplayIdleService::updateScreensaver() {
} }
void DisplayIdleService::tick() { void DisplayIdleService::tick() {
// Check if MCP override is active — must not be auto-stopped by idle logic
// READ OUTSIDE LVGL lock to avoid lock inversion:
// MCP video task locks mutex -> LVGL, we must NOT do LVGL -> mutex
bool isMcpActive = false;
{
auto& st = mcp::getState();
std::lock_guard<std::mutex> lk(st.mutex);
isMcpActive = (st.drawArea != nullptr) || st.overrideActive;
}
if (!lvgl::lock(100)) { if (!lvgl::lock(100)) {
return; return;
} }
@@ -163,14 +173,6 @@ void DisplayIdleService::tick() {
uint32_t inactive_ms = 0; uint32_t inactive_ms = 0;
inactive_ms = lv_display_get_inactive_time(nullptr); inactive_ms = lv_display_get_inactive_time(nullptr);
// Check if MCP override is active — it must not be auto-stopped by idle logic
bool isMcpActive = false;
{
auto& st = mcp::getState();
std::lock_guard<std::mutex> lk(st.mutex);
isMcpActive = (st.drawArea != nullptr) || st.overrideActive;
}
// Only update if not stopping (prevents lag on touch) — skip for MCP (no animation) // Only update if not stopping (prevents lag on touch) — skip for MCP (no animation)
if (displayDimmed && screensaverOverlay && !stopScreensaverRequested.load(std::memory_order_acquire) && !isMcpActive) { if (displayDimmed && screensaverOverlay && !stopScreensaverRequested.load(std::memory_order_acquire) && !isMcpActive) {
// Check if screensaver should auto-off after 5 minutes // Check if screensaver should auto-off after 5 minutes