]> Repositories - Adafruit_Blinka-hackapet.git/commitdiff
Do not prematurely stop waiting for an answer from the message queue
authorMichael Lass <bevan@bi-co.net>
Fri, 30 Oct 2020 22:57:10 +0000 (23:57 +0100)
committerMichael Lass <bevan@bi-co.net>
Fri, 30 Oct 2020 23:24:25 +0000 (00:24 +0100)
When requesting data from libgpiod_pulsein via the message queue, we
always expect an answer. Prematurely stopping to wait for an answer can
only do harm. If we do not read the expected answer from the mq, it will
stay there and be read (falsely) as an answer to the following request.

Example:

* We request a pulse length by sending '^'.
* Due to high system load, libgpiod_pulsein does not send a response in
  time.
* We timeout with a RuntimeError. This is verly likely ignored by the
  calling code since RuntimeErrors are thrown with every invalid
  reading such that the calling code _has to_ ignore these errors.
* We trigger a new sensor reading (pause-clean-resume).
* We request the length of the pulse buffer by sending 'l'.
* We read from the message queue. The response we get now is the
  response to our original '^' request. Let this response be 100.
* We now assume 100 elements in the pulse buffer. This is of course
  wrong and will lead to all sorts of errors.

The only reason to timeout on an expected answer is probably during
initialization when we are not sure if the communication via message
queue has been successfully set up. In all other cases we should just
block and never timeout.

src/adafruit_blinka/microcontroller/bcm283x/pulseio/PulseIn.py

index aef942a6c93319a37578bfb503ec07ebb56bbc4a..19dc98f32089364b6e266712f07ce39038dda5e1 100644 (file)
@@ -70,26 +70,29 @@ class PulseIn:
         # wait for it to start up
         if DEBUG:
             print("Waiting for startup success message from subprocess")
-        message = self._wait_receive_msg()
+        message = self._wait_receive_msg(timeout=0.25)
         if message[0] != b"!":
             raise RuntimeError("Could not establish message queue with subprocess")
         self._paused = False
 
     # pylint: disable=redefined-builtin
-    def _wait_receive_msg(self, timeout=0.25, type=2):
+    def _wait_receive_msg(self, timeout=0, type=2):
         """Internal helper that will wait for new messages of a given type,
         and throw an exception on timeout"""
-        stamp = time.monotonic()
-        while (time.monotonic() - stamp) < timeout:
-            try:
-                message = self._mq.receive(block=False, type=type)
-                return message
-            except sysv_ipc.BusyError:
-                time.sleep(0.001)  # wait a bit then retry!
-        # uh-oh timed out
-        raise RuntimeError(
-            "Timed out waiting for PulseIn message. Make sure libgpiod is installed."
-        )
+        if timeout > 0:
+            stamp = time.monotonic()
+            while (time.monotonic() - stamp) < timeout:
+                try:
+                    message = self._mq.receive(block=False, type=type)
+                    return message
+                except sysv_ipc.BusyError:
+                    time.sleep(0.001)  # wait a bit then retry!
+            # uh-oh timed out
+            raise RuntimeError(
+                "Timed out waiting for PulseIn message. Make sure libgpiod is installed."
+            )
+        message = self._mq.receive(block=True, type=type)
+        return message
 
     # pylint: enable=redefined-builtin