pschichtel/JavaCAN

read() in separate thread not returning on close()

ekuemmel opened this issue · 6 comments

Hello Phillip. I like that implementation and use it on a Raspberry. So far I had only one issue and this is about proper shutdown of an application. I have CAN socket (e.g. rawCanChannel) read() running in a separate thread and it should return when a close() is called from main thread. This is not happening (if i am not mistaken) and therefore the whole application can not be terminated since it hangs in read() forever.
Thanks
Eberhard

Are you using blocking IO?

Would it be possible to provide a minimal reproducer for your issue?

Thank you for the quick reply. I created a small example application attached here.

demo.zip

I would expect that a read() done in a reader thread returns either with an exception or with null when the socket is closed from main thread.
This example listens max. 10 seconds to the CAN and closes then. The close is hanging and the application never terminates.

Thanks the reproducer. I wasn't sure my self if this is something that is even supposed to work and found this after a bit of googling: https://stackoverflow.com/questions/40301754/c-blocking-read-should-return-if-filedescriptor-is-deleted

So this is not a JavaCAN problem, but basically a misuse of the socket API. If the reproducer is representitve of your program, I can really recommend event-driven IO using a the EPollSelector (this will create a standard Java Selector in the 2.x branch or a custom IOSelector on master). The Selector API allows to be interrupted. You might also want to have a look at the CanBroker and maybe even the EventLoop.

At least it works for streams. Closing the stream from another thread is same as reaching end of stream. The reaction is:

"Reads the next byte of data from the input stream. The value byte isreturned as an int in the range 0 to 255. If no byte is available because the end of the streamhas been reached, the value -1 is returned. This methodblocks until input data is available, the end of the stream is detected,or an exception is thrown. "

But maybe this is also not a safe way to do it. Thanks again for support.

The RawCanChannel class (same for IsotpCanChannel) is a pretty thin wrapper around the C socket(), read(), write() and close() syscalls. JavaCAN should behave exactly how these syscalls would in a C program, so in case things are unclear around the behaviour, you might also want to check the man pages of them. I'll add hints about this to the readme.

I generally consider wrong usage a documentation bug, so feel free to report more of these as they come up :)

I'll modify my code by calling read() only after a selector event.