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:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user