hartkopp/can-isotp

read() does not return after a call to close()

Opened this issue · 4 comments

Sauci commented

In the main(), I'm opening a can-isotp socket, and I perform write() operation on it. This part is working, the expected CAN frames are sent on the bus.
Now, I'm performing a blocking call to read() on a separated thread. This part is also working, I'm receiving the expected CAN frames.
The issue arises when I'm calling close() on the main() function. I would expect the read() function to return an error (such as EBADF or something similar), but instead of this, it keeps blocking, while the close() function returns 0.
Is it the expected behaviour? If it is the case, what is the proper way to exit from a blocking read()?

I was not aware about this blocking read in a multithreaded environment. So I googled it for myself and found this:
https://stackoverflow.com/questions/16637086/linux-cancel-blocking-read
I don't know if this is a general problem with multithreading and if other Kernel syscall interfaces have a 'better' solution that returns the read call when closing the socket.
The isotp implementation passes received PDUs via sock_queue_rcv_skb(sk, skb), see here:
https://elixir.bootlin.com/linux/v5.10.8/source/net/can/isotp.c#L239
So I only pass the data to the receive queue which is then passed 'somehow' to the user space.
I wonder if we can add some code to isotp_release() that triggers blocking readers to return?!?
I will take a look into other sockets 'release' code in the kernel ...

Sauci commented

@hartkopp thank you for your detailed response. I will give a try to the SO link you shared.
Concerning the isotp_release() code: In the past I've used the J1939 stack, which behaves as described in the initial issue (error returned from read when the socket get closed). I hope it might help

Thanks for the hint! I'll take a look at it.

I got a similar report a while back on my JavaCAN lib (a thin wrapper around SocketCAN) and the reporter had the same issue with a CAN_RAW socket too. Back then I found this which made sense to me.