From 177f0def0d20d01eca2e2dbaefdc16c6005d6221 Mon Sep 17 00:00:00 2001 From: Wentao Chen Date: Mon, 29 Jan 2024 14:15:41 +0100 Subject: [PATCH] Rework "Fix race condition bugs" to fix pytest failure --- j1939/electronic_control_unit.py | 39 +++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/j1939/electronic_control_unit.py b/j1939/electronic_control_unit.py index e3fb05d..82b7573 100644 --- a/j1939/electronic_control_unit.py +++ b/j1939/electronic_control_unit.py @@ -29,6 +29,8 @@ def __init__(self, data_link_layer='j1939-21', max_cmdt_packets=1, minimum_tp_rt self._bus = None # Locking object for send self._send_lock = threading.Lock() + # Locking object for _timer_events list + self._events_list_lock = threading.Lock() if max_cmdt_packets > 0xFF: raise ValueError("max number of segments that can be sent is 0xFF") @@ -85,7 +87,13 @@ def add_timer(self, delta_time, callback, cookie=None): 'cookie': cookie, } - self._timer_events.append( d ) + res = self._events_list_lock.acquire(timeout = 1.0) + if res: + self._timer_events.append( d ) + self._events_list_lock.release() + else: + logger.error("_events_list_lock acquire failed") + self._job_thread_wakeup() def remove_timer(self, callback): @@ -94,9 +102,19 @@ def remove_timer(self, callback): :param callback: The callback to be removed from the timer event list """ - for event in self._timer_events: - if event['callback'] == callback: - self._timer_events.remove( event ) + res = self._events_list_lock.acquire(timeout = 1.0) + if res: + for event in self._timer_events[:]: + if event['callback'] == callback: + try: + self._timer_events.remove( event ) + except Exception as e: + logger.error(str(e)) + + self._events_list_lock.release() + else: + logger.error("_events_list_lock acquire failed") + self._job_thread_wakeup() def connect(self, *args, **kwargs): @@ -282,7 +300,7 @@ def _async_job_thread(self): next_wakeup = self.j1939_dll.async_job_thread(now) # check timer events - for event in self._timer_events: + for event in self._timer_events[:]: if event['deadline'] > now: if next_wakeup > event['deadline']: next_wakeup = event['deadline'] @@ -299,7 +317,16 @@ def _async_job_thread(self): next_wakeup = event['deadline'] else: # remove from list - self._timer_events.remove( event ) + res = self._events_list_lock.acquire(timeout = 1.0) + if res: + try: + self._timer_events.remove( event ) + except Exception as e: + logger.error(str(e)) + + self._events_list_lock.release() + else: + logger.error("_events_list_lock acquire failed") time_to_sleep = next_wakeup - time.time() if time_to_sleep > 0: