InfiniTime.git

commit f6d7f602f57f93dbf5a68a371cc1a9d019e1408d

Author: Jean-François Milants <jf@codingfield.com>

Fix deadlock when a lot of notifications are received in a very short time span.

When a notification is received, SystemTask sends messages to DisplayApp, which loads the Notifications apps that sends a few messages to SystemApp.
When notification are received too quickly, DisplayApp and SystemTask cannot process those messages fast enough (probably because of the time it takes to refresh the display) and the message queues fill up. When they are full, the current implementation just waits until there's room available to store the event. In this case, since both tasks exchange messages, they end up in a deadlock.

This fix consists in setting the timeout value to 0 (non-blocking mode) for the NewNotification messages on the DisplayApp side. This will prevent the SystemTask from being blocked (which would result in the watchdog reseting the watch). A more generic approach should be design in the future.

 src/displayapp/DisplayApp.cpp | 10 +++++++++-


diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp
index cd941f16ccdcff573ba3aad3392d6c5818ac9c77..682ea12cb37e048944068aebe420d67ae15bcc59 100644
--- a/src/displayapp/DisplayApp.cpp
+++ b/src/displayapp/DisplayApp.cpp
@@ -560,7 +560,15 @@     if (xHigherPriorityTaskWoken == pdTRUE) {
       portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
     }
   } else {
-    xQueueSend(msgQueue, &msg, portMAX_DELAY);
+    TickType_t timeout = portMAX_DELAY;
+    // Make xQueueSend() non-blocking if the message is a Notification message. We do this to avoid
+    // deadlock between SystemTask and DisplayApp when their respective message queues are getting full
+    // when a lot of notifications are received on a very short time span.
+    if (msg == Messages::NewNotification) {
+      timeout = static_cast<TickType_t>(0);
+    }
+
+    xQueueSend(msgQueue, &msg, timeout);
   }
 }