Skip to content

Commit b890103

Browse files
committed
emcy: Fix maximum timeout logic errors in EmcyConsumer.wait().
If an EMCY package was received, but filtered out by the emcy_code matching, the condition waiting is started again with the same timeout. Thus the actual maximum waiting time is not correctly limited to the given argument, as the docstring promises. Track the remaining time until the initial deadline instead, as basis for the condition wait. Further, spurious wake-ups from the condition wait on the OS level are not handled correctly. The threading.Condition docs explicitly recommend checking the shared state (number of logged entries in this case) in the while loop, because the wait() call may abort early. The current code assumes that this necessarily indicates a timeout, without checking the actually passed time again. Reorder the check against end_time in the loop to avoid this.
1 parent 9aab2d4 commit b890103

1 file changed

Lines changed: 9 additions & 6 deletions

File tree

canopen/emcy.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,19 @@ def wait(
6969
while True:
7070
with self.emcy_received:
7171
prev_log_size = len(self.log)
72-
self.emcy_received.wait(timeout)
72+
remaining = end_time - time.time()
73+
if remaining <= 0:
74+
return None # Actual timeout reached
75+
self.emcy_received.wait(remaining)
7376
if len(self.log) == prev_log_size:
74-
# Resumed due to timeout
75-
return None
77+
if time.time() >= end_time:
78+
# Resumed due to timeout
79+
return None
80+
else:
81+
continue
7682
# Get last logged EMCY
7783
emcy = self.log[-1]
7884
logger.info("Got %s", emcy)
79-
if time.time() > end_time:
80-
# No valid EMCY received on time
81-
return None
8285
if emcy_code is None or emcy.code == emcy_code:
8386
# This is the one we're interested in
8487
return emcy

0 commit comments

Comments
 (0)