python-can icon indicating copy to clipboard operation
python-can copied to clipboard

Mac OS: Deleting two separate PCAN buses simultaneously causes hard python script exit (assertion failed)

Open bertbroer opened this issue 1 year ago • 0 comments

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

bertbroer avatar Feb 29 '24 13:02 bertbroer