diff --git a/can/interfaces/ics_neovi/neovi_bus.py b/can/interfaces/ics_neovi/neovi_bus.py index 3df0ccc39..176747ad2 100644 --- a/can/interfaces/ics_neovi/neovi_bus.py +++ b/can/interfaces/ics_neovi/neovi_bus.py @@ -11,6 +11,8 @@ """ import logging +import os +import tempfile from collections import deque from can import Message, CanError, BusABC @@ -28,6 +30,35 @@ ics = None +try: + from filelock import FileLock +except ImportError as ie: + + logger.warning( + "Using ICS NeoVi can backend without the " + "filelock module installed may cause some issues!: %s", + ie, + ) + + class FileLock: + """Dummy file lock that does not actually do anything""" + + def __init__(self, lock_file, timeout=-1): + self._lock_file = lock_file + self.timeout = timeout + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + return None + + +# Use inter-process mutex to prevent concurrent device open. +# When neoVI server is enabled, there is an issue with concurrent device open. +open_lock = FileLock(os.path.join(tempfile.gettempdir(), "neovi.lock")) + + class ICSApiError(CanError): """ Indicates an error with the ICS API. @@ -122,7 +153,9 @@ def __init__(self, channel, can_filters=None, **kwargs): type_filter = kwargs.get("type_filter") serial = kwargs.get("serial") self.dev = self._find_device(type_filter, serial) - ics.open_device(self.dev) + + with open_lock: + ics.open_device(self.dev) if "bitrate" in kwargs: for channel in self.channels: diff --git a/setup.py b/setup.py index 1918b644b..fb1a4de54 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,10 @@ long_description = f.read() # Dependencies -extras_require = {"serial": ["pyserial~=3.0"], "neovi": ["python-ics>=2.12"]} +extras_require = { + "serial": ["pyserial~=3.0"], + "neovi": ["python-ics>=2.12", "filelock"], +} tests_require = [ "pytest~=4.3", @@ -90,6 +93,7 @@ "wrapt~=1.10", "aenum", 'windows-curses;platform_system=="Windows"', + "filelock", ], setup_requires=["pytest-runner"], extras_require=extras_require,