Skip to content

isotp error handler not propagated to uds connection #233

Description

@elupus

When a isotp error occurs, it triggers a call to a callback, that one can supply to the constructor of the isotp stack called error_handler. The default of this callback is to just log an message to log.

The uds stack should be informed of this error and abort on-going requests in PythonIsoTpConnection.specific_wait_frame. With log request timeouts, it can take a long time for the request to abort. It also aborts with a TimeoutException instead of the actual low level fault.

Activity

  1. elupus commented on May 23, 2024

    @elupus
    Author

    In general i might be that the protocol._stop_receiving() or _stop_sending() call is not propagated to the listener. not all error_handler calls abort the reception.

  2. elupus commented on May 23, 2024

    @elupus
    Author

    Did the following hack to work around it:

    class Connection(PythonIsoTpConnection):
        def transport_error(self, exception: Exception):
            self.fromIsoTPQueue.put(exception)
    
        def specific_wait_frame(self, timeout=2):
            if not self.opened:
                raise RuntimeError("Connection is not open")
    
            frame = None
            try:
                frame = self.fromIsoTPQueue.get(block=True, timeout=timeout)
            except queue.Empty as exception:
                raise TimeoutException("Did not receive frame IsoTP Transport layer in time (timeout=%s sec)" % timeout) from exception
    
            if isinstance(frame, Exception):
                raise frame
    
            if self.mtu is not None:
                if frame is not None and len(frame) > self.mtu:
                    self.logger.warning("Truncating received payload to a length of %d" % (self.mtu))
                    frame = frame[0:self.mtu]
    
            return bytes(frame)  # isotp.protocol.TransportLayer uses bytearray. udsoncan is strict on bytes format
    

    Then hook that transport error into the isotp.CanStack.

    
            connection: Connection
            def transport_error(exception: Exception):
                connection.transport_error(exception)
    
            transport = isotp.CanStack(
                self.bus,
                address=isotp_addr,
                params=isotp_params,
                error_handler=transport_error,
            )
            connection = Connection(transport)
    

    But it gets ugly due to when and how the transport_error is registered. Maybe the recv() function of isotp should be changed to propagate these exceptions? In my case it's usually been "FlowControlTimeoutError: Reception of FlowControl timed out. Stopping transmission" that causes issues.

  3. pylessard commented on May 26, 2024

    @pylessard
    Owner

    Thanks, I see what you mean. The error should be reported to the upper layer.
    I will check this, but maybe not short term.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions