Am 11.05.21 um 21:02 schrieb Patrick Menschel: > Am 11.05.21 um 19:44 schrieb Oliver Hartkopp: >> On 11.05.21 18:37, Patrick Menschel wrote: >>> Am 10.05.21 um 20:04 schrieb Patrick Menschel: >>>> Am 10.05.21 um 12:02 schrieb Bartosz Zdanowicz: >>>>> pt., 7 maj 2021 o 09:59 Patrick Menschel <menschel.p@xxxxxxxxx> >>>>> napisał(a): >>>>>> try to enable CAN_ISOTP_WAIT_TX_DONE via socket.setsockopt() . >>>>>> https://github.com/raspberrypi/linux/blob/rpi-5.10.y/net/can/isotp.c#L14 >>>>>> >>>>>> >>>>>> https://gitlab.com/Menschel/socketcan/-/blob/master/socketcan/socketcan.py#L583 >>>>>> >>>>>> >>>>>> and wrap tx into a try-except block. >>>>>> >>>>>> try: >>>>>> self.process_data(socket=socket) >>>>>> except OSError as e: >>>>>> print(e) >>>>>> >>>>>> With this you actually have a chance to do error handling on tx path >>>>>> instead of hitting an already present error of the previous op. >>>>>> >>>>> I used following code: >>>>> >>>>> import isotp >>>>> import time >>>>> s = isotp.socket() >>>>> s._socket.settimeout(2) >>>>> s.set_opts(s.flags.WAIT_TX_DONE) >>>>> s.bind("can0", isotp.Address(rxid=1, txid=2)) >>>>> >>>>> s.send(b"aaaaaaaaa") -> returns immediately with number of bytes >>>>> s.send(b"aaaaaaaaa") -> same OS error as above (Error 70) >>>>> >>>> >>>> OK, >>>> >>>> this is really strange. I have no clue how that is possible unless it's >>>> on kernel side. >>>> >>>> I have to write a test for it later. >>> >>> I can confirm this behaviour, it is definetly kernel-side of the socket. >>> >>> tests/test_socketcan.py::TestCanIsoTpSocket::test_should_fail_missing_flow_control_on_transfer >>> >>> >>> -------------------------------------------------------------------------------------------------- >>> >>> live log call >>> -------------------------------------------------------------------------------------------------- >>> >>> 2021-05-11 18:14:00 [ INFO] Return value of IsoTpSend without flow >>> control: 64 (test_socketcan.py:720) >>> 2021-05-11 18:14:01 [ ERROR] Return value of IsoTpSend without flow >>> control: None, Raised [Errno 70] Communication error on send >>> (test_socketcan.py:718) >>> >>> Apparently there is another message thread for this and something was >>> fixed. >>> >>> https://marc.info/?i=97e2ddd5-cc8b-9c7b-6198-2eceee39dfd4%20()%20hartkopp%20!%20net >>> >>> >>> Funny thing is, it does not care about the wait_tx_done flag, this >>> happens with and without it. >> >> The error handling was originally intended to be done by simple timeout >> monitoring on application level. >> >> What I assume from the output above: >> >> 1st attempt: We have a failure but we happily return that we have send >> 64 bytes (which Marc improved with the above referenced patch for >> CAN_ISOTP_WAIT_TX_DONE mode). >> >> (socket remains open?!?) >> >> 2nd attempt: The error from the first attempt shows up in the socket >> error message queue?!? >> >> I just did some tests with a modified isotpsend.c which closes the >> socket after the sending operation. This is probably the reason I did >> not see that behaviour ... > > I forgot to post my test which produced that result above. > > https://gitlab.com/Menschel/socketcan/-/commit/bd7bfebde1d791c7dccb717c849398c0d0f53dcd > > I run it on a pi0w with regular raspbian buster and a recent python > 3.9.4 installed. > "pytest > tests/test_socketcan.py::TestCanIsoTpSocket::test_should_fail_missing_flow_control_on_transfer" Just tying some loose ends here. I rewrote the test to be in line with pytest convention. "can_interface" is a pytest fixture which will use any CAN interface that is available. OSError is expected so it fails. Regards, Patrick https://gitlab.com/Menschel/socketcan/-/blob/master/tests/test_socketcan.py#L708 ==================================================================================================== FAILURES ===================================================================================================== ______________________________________________________________________ TestCanIsoTpSocket.test_should_fail_missing_flow_control_on_transfer _______________________________________________________________________ self = <tests.test_socketcan.TestCanIsoTpSocket object at 0xb55d2370>, can_interface = 'mcp1' def test_should_fail_missing_flow_control_on_transfer(self, can_interface): rx_addr = 0x18DA01FA tx_addr = 0x18DAFA01 s = CanIsoTpSocket(interface=can_interface, rx_addr=rx_addr, tx_addr=tx_addr) data = bytes(range(64)) with pytest.raises(OSError): > err = s.send(data) E Failed: DID NOT RAISE <class 'OSError'> tests/test_socketcan.py:714: Failed ________________________________________________________________ TestCanIsoTpSocket.test_should_fail_missing_flow_control_on_transfer_and_wait_tx _________________________________________________________________ self = <tests.test_socketcan.TestCanIsoTpSocket object at 0xb55d28b0>, can_interface = 'mcp1' def test_should_fail_missing_flow_control_on_transfer_and_wait_tx(self, can_interface): rx_addr = 0x18DA01FA tx_addr = 0x18DAFA01 s = CanIsoTpSocket(interface=can_interface, rx_addr=rx_addr, tx_addr=tx_addr, wait_tx_done=True) data = bytes(range(64)) with pytest.raises(OSError): > err = s.send(data) E Failed: DID NOT RAISE <class 'OSError'> tests/test_socketcan.py:722: Failed