Skip to content

Commit e869fb7

Browse files
pierreluctgPierre-Luc Tessier Gagné
andauthored
Fix ThreadBasedCyclicSendTask thread not being stopped on Windows (#1679)
Also adding unit test to cover RestartableCyclicTaskABC Co-authored-by: Pierre-Luc Tessier Gagné <[email protected]>
1 parent b2689ae commit e869fb7

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

can/broadcastmanager.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,10 @@ def __init__(
269269
self.start()
270270

271271
def stop(self) -> None:
272-
if USE_WINDOWS_EVENTS:
273-
win32event.CancelWaitableTimer(self.event.handle)
274272
self.stopped = True
273+
if USE_WINDOWS_EVENTS:
274+
# Reset and signal any pending wait by setting the timer to 0
275+
win32event.SetWaitableTimer(self.event.handle, 0, 0, None, None, False)
275276

276277
def start(self) -> None:
277278
self.stopped = False

test/simplecyclic_test.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,41 @@ def test_stopping_perodic_tasks(self):
152152

153153
bus.shutdown()
154154

155+
def test_restart_perodic_tasks(self):
156+
period = 0.01
157+
safe_timeout = period * 5
158+
159+
msg = can.Message(
160+
is_extended_id=False, arbitration_id=0x123, data=[0, 1, 2, 3, 4, 5, 6, 7]
161+
)
162+
163+
with can.ThreadSafeBus(interface="virtual", receive_own_messages=True) as bus:
164+
task = bus.send_periodic(msg, period)
165+
self.assertIsInstance(task, can.broadcastmanager.RestartableCyclicTaskABC)
166+
167+
# Test that the task is sending messages
168+
sleep(safe_timeout)
169+
assert not bus.queue.empty(), "messages should have been transmitted"
170+
171+
# Stop the task and check that messages are no longer being sent
172+
bus.stop_all_periodic_tasks(remove_tasks=False)
173+
sleep(safe_timeout)
174+
while not bus.queue.empty():
175+
bus.recv(timeout=period)
176+
sleep(safe_timeout)
177+
assert bus.queue.empty(), "messages should not have been transmitted"
178+
179+
# Restart the task and check that messages are being sent again
180+
task.start()
181+
sleep(safe_timeout)
182+
assert not bus.queue.empty(), "messages should have been transmitted"
183+
184+
# Stop all tasks and wait for the thread to exit
185+
bus.stop_all_periodic_tasks()
186+
if isinstance(task, can.broadcastmanager.ThreadBasedCyclicSendTask):
187+
# Avoids issues where the thread is still running when the bus is shutdown
188+
task.thread.join(safe_timeout)
189+
155190
@unittest.skipIf(IS_CI, "fails randomly when run on CI server")
156191
def test_thread_based_cyclic_send_task(self):
157192
bus = can.ThreadSafeBus(interface="virtual")

0 commit comments

Comments
 (0)