Mac OS: Deleting two separate PCAN buses simultaneously causes hard python script exit (assertion failed)
Describe the bug
Note; I can reproduce this error on Mac OS. On Windows it seems to run fine.
When two (threadsafe) buses are deleted simultaneously, the library is unable to obtain a mutex to uninitialize the second while it's handling the first. This causes the script to exit due to an assertion failure.
Assertion failed: (0 == pthread_mutex_lock(&usbDevice[hDevice].ptMutex)), function pcan_usb_drv_disconnect, file pcan_drv.c, line 3979.
This is caused because self.__m_dllBasic.CAN_Uninitialize(Channel) on the second instance is called, before the first is completed.
To Reproduce
Run the following code, without any PCAN hardware attached:
import can
import threading
def start_can1():
bus1 = can.ThreadSafeBus(interface="pcan", channel="PCAN_USBBUS1")
for msg in bus1:
print(msg)
def start_can2():
bus2 = can.ThreadSafeBus(interface="pcan", channel="PCAN_USBBUS2")
for msg in bus2:
print(msg)
if __name__ == "__main__":
try:
t1 = threading.Thread(target=start_can1)
t2 = threading.Thread(target=start_can2)
t1.start()
t2.start()
t1.join()
t2.join()
except:
pass
print("Aaaaaaaand it's gone...")
Expected behavior
I would expect a normal exception that can be handled within Python.
Additional context
OS and version: MacOS Ventura 13.0 Python version: 3.10.9 python-can version: 4.3.1 python-can interface/s (if applicable): PCAN
Traceback and logs
Exception in thread Thread-1 (start_can1):
Traceback (most recent call last):
File "/Users/local/.pyenv/versions/3.10.9/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
Exception in thread Thread-2 (start_can2):
Traceback (most recent call last):
File "/Users/local/.pyenv/versions/3.10.9/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
self.run()
File "/Users/local/.pyenv/versions/3.10.9/lib/python3.10/threading.py", line 953, in run
self.run()
File "/Users/local/.pyenv/versions/3.10.9/lib/python3.10/threading.py", line 953, in run
self._target(*self._args, **self._kwargs)
File "/Users/local/Workspace/playground/pcancrash/main.py", line 5, in start_can1
self._target(*self._args, **self._kwargs)
File "/Users/local/Workspace/playground/pcancrash/main.py", line 10, in start_can2
bus1 = can.ThreadSafeBus(interface="pcan", channel="PCAN_USBBUS1")
File "/Users/local/Workspace/playground/pcancrash/.venv/lib/python3.10/site-packages/can/thread_safe_bus.py", line 39, in __init__
bus2 = can.ThreadSafeBus(interface="pcan", channel="PCAN_USBBUS2")
File "/Users/local/Workspace/playground/pcancrash/.venv/lib/python3.10/site-packages/can/thread_safe_bus.py", line 39, in __init__
super().__init__(Bus(*args, **kwargs))
File "/Users/local/Workspace/playground/pcancrash/.venv/lib/python3.10/site-packages/can/util.py", line 378, in wrapper
super().__init__(Bus(*args, **kwargs))
File "/Users/local/Workspace/playground/pcancrash/.venv/lib/python3.10/site-packages/can/util.py", line 378, in wrapper
return f(*args, **kwargs)
File "/Users/local/Workspace/playground/pcancrash/.venv/lib/python3.10/site-packages/can/interface.py", line 135, in Bus
return f(*args, **kwargs)
File "/Users/local/Workspace/playground/pcancrash/.venv/lib/python3.10/site-packages/can/interface.py", line 135, in Bus
bus = cls(channel, **kwargs)
File "/Users/local/Workspace/playground/pcancrash/.venv/lib/python3.10/site-packages/can/interfaces/pcan/pcan.py", line 303, in __init__
bus = cls(channel, **kwargs)
File "/Users/local/Workspace/playground/pcancrash/.venv/lib/python3.10/site-packages/can/interfaces/pcan/pcan.py", line 303, in __init__
raise PcanCanInitializationError(self._get_formatted_error(result))
can.interfaces.pcan.pcan.PcanCanInitializationError: The value of a handle (PCAN-Channel, PCAN-Hardware, PCAN-Net, PCAN-Client) is invalid
PcanBus was not properly shut down
raise PcanCanInitializationError(self._get_formatted_error(result))
can.interfaces.pcan.pcan.PcanCanInitializationError: The value of a handle (PCAN-Channel, PCAN-Hardware, PCAN-Net, PCAN-Client) is invalid
PcanBus was not properly shut down
Assertion failed: (0 == pthread_mutex_lock(&usbDevice[hDevice].ptMutex)), function pcan_usb_drv_disconnect, file pcan_drv.c, line 3979.
[1] 345 abort python main.py