Skip to content

SocketcanBus.send() timeout semantics differ from BusABC.send() #2005

@ottojo

Description

@ottojo

Describe the bug

In the send() method of BusABC, the optional timeout argument is documented as

If > 0, wait up to this many seconds for message to be ACK'ed or
for transmit queue to be ready depending on driver implementation.
If timeout is exceeded, an exception will be raised.
Might not be supported by all interfaces.
None blocks indefinitely.

but the SocketcanBus implementation of BusABC documents (and implements) it like this:

Wait up to this many seconds for the transmit queue to be ready.
If not given, the call may fail immediately.

It looks to me like the handling in SocketcanBus just doesn't conform to the expected interface, in particular it does

# If no timeout is given, poll for availability
if timeout is None:
    timeout = 0

which results in nonblocking behavior and potentially raising can.CanOperationError("Transmit buffer full") instead of waiting indefinitely when no timeout is specified.

To Reproduce

msg = can.Message(
    arbitration_id=0x123, is_extended_id=False, data=[1, 2, 3, 4, 5, 6, 7, 8]
)
with can.Bus(interface="socketcan", channel="can0") as bus:
    for i in range(10000):
        bus.send(msg)

Observe that sending fails if the sending rate exceeds the capacity of the bus, instead of blocking and waiting.

Expected behavior

As the timeout is None, blocking indefinitely until the transmit queue is ready, as specified in the BusABC.send() docs.

Additional context

OS and version: Ubuntu 24.04.3 LTS, 6.14.0-35-generic
Python version: Python 3.12.3
python-can version: 4.3.1
python-can interface/s (if applicable): socketcan, F81601 interface (PCI), Manufacturer provided driver

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions