hardbyte / hardbyte/python-can

ThreadSafeBus implementation is ignored from inside the library

Abierto
#1,620 3 comentarios 0 reacciones 0 asignados Ver en GitHub
bug
Lenguaje dominante
Python
Estrellas
1.6k
Forks
697
Métricas de merge de PR
Sin PR fusionados en 30 d

Descripción

### Describe the bug
`ThreadSafeBus` implementation of `send` method is not used when it's called from inside the library. This means that **for all `send_periodic` implementation, `ThreadSafeBus` is completely ignored and `send` method of the concrete bus is used directly**.

### To Reproduce
Use `send_periodic` in `ThreadSafeBus` to observe that thread safe implementation of `send` function is not used. See "Traceback and logs" for code example.

### Expected behavior
`send_periodic` implementation should use `ThreadSafeBus` implementation of `send`. According to the implementation, it is definitely expected.
https://github.com/hardbyte/python-can/blob/dc0ae68acb28f01a503e084718cfa2acf39d1e16/can/thread_safe_bus.py#L61-L62

Below the dummy lock is created:
https://github.com/hardbyte/python-can/blob/dc0ae68acb28f01a503e084718cfa2acf39d1e16/can/thread_safe_bus.py#L41-L43

And here this lock is "used" - actually it's doing nothing, since the `send` implementation should be synchronized in `ThreadSafeBus`.
https://github.com/hardbyte/python-can/blob/dc0ae68acb28f01a503e084718cfa2acf39d1e16/can/broadcastmanager.py#L299-L300

### Additional context
This behavior was replicated using hardware `vector` bus.
As this issue is critical for our use case, we used a following workaround - inject the `send` lock in place of the dummy periodic lock after `ThreadSafeBus` was initialized:
```python
bus.__wrapped__._lock_send_periodic = bus._lock_send
```

OS and version: `Windows 10 Enterprise 10.0.19045 Build 19045`
Python version: `Python 3.11.0 (main, Oct 24 2022, 18:26:48) [MSC v.1933 64 bit (AMD64)] on win32`
python-can version: `4.2.2`
python-can interface/s (if applicable): `virtual`, `vector`

Traceback and logs

Simple code example, in which frames are sent both periodically and manually:
```python
import time
import can

bus = can.ThreadSafeBus(
interface='virtual',
receive_own_messages=True
)

msg_periodic = can.Message(
arbitration_id=0x123, data=[1, 2, 3, 4, 5, 6], is_extended_id=False
)
msg_manual = can.Message(
arbitration_id=0x234, data=[7, 8, 9], is_extended_id=False
)

# periodic send
task = bus.send_periodic(msg_periodic, 0.2)
assert isinstance(task, can.CyclicSendTaskABC)

# manual send
bus.send(msg_manual)

# receive
start_time = time.time()
while time.time() - start_time < 1:
rec_msg = bus.recv(1)
print(rec_msg)
task.stop()
```

To observe the bug, `print` statements are injected into `ThreadSafeBus`:
```python
def recv(
self, timeout=None, *args, **kwargs
): # pylint: disable=keyword-arg-before-vararg
print(f'Using thread safe recv')
with self._lock_recv:
return self.__wrapped__.recv(timeout=timeout, *args, **kwargs)

def send(
self, msg, timeout=None, *args, **kwargs
): # pylint: disable=keyword-arg-before-vararg
print(f'Using thread safe send {msg=}')
with self._lock_send:
return self.__wrapped__.send(msg, timeout=timeout, *args, **kwargs)
```

Executing above gives following output:
```
Using thread safe send msg=can.Message(timestamp=0.0, arbitration_id=0x234, is_extended_id=False, dlc=3, data=[0x7, 0x8, 0x9])
Using thread safe recv
Timestamp: 1687888509.605106 ID: 0123 S Tx DL: 6 01 02 03 04 05 06
Using thread safe recv
Timestamp: 1687888509.605106 ID: 0234 S Tx DL: 3 07 08 09
Using thread safe recv
Timestamp: 1687888509.805578 ID: 0123 S Tx DL: 6 01 02 03 04 05 06
Using thread safe recv
Timestamp: 1687888510.005523 ID: 0123 S Tx DL: 6 01 02 03 04 05 06
Using thread safe recv
Timestamp: 1687888510.206290 ID: 0123 S Tx DL: 6 01 02 03 04 05 06
Using thread safe recv
Timestamp: 1687888510.406522 ID: 0123 S Tx DL: 6 01 02 03 04 05 06
Using thread safe recv
Timestamp: 1687888510.606262 ID: 0123 S Tx DL: 6 01 02 03 04 05 06
```

Manual call of `bus.send` worked correctly and `ThreadSafeBus` implementation was used. However, periodically sent frames ignored thread-safe implementation of `send` (no print), but the frames were sent on the bus.

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.