Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linux, cancel blocking read()

In a multi-threaded Linux program used for serial communication, is it possible (and what would be the best approach) to terminate a blocking read() call from another thread?

I would like to keep everything as reactive as possible and avoid any use of timeouts with repeated polling.

The background of this question is that I'm trying to create a Scala serial communication library for Linux using JNI. I'm trying to keep the native side as simple as possible providing, amongst others, a read() and close() function. On the Scala side, one thread would call read() and block until data from the serial port is available. However, the serial port can be closed by other means, resulting in a call to close(). Now, to free up the blocked thread, I would somehow need to cancel the system read call.

like image 907
Jakob Odersky Avatar asked May 19 '13 16:05

Jakob Odersky


3 Answers

One fairly popular trick: instead of blocking in read(), block in select() on both your serial-socket and a pipe. Then when another thread wants to wake up your thread, it can do so by writing a byte to the other end of that pipe. That byte will cause select() to return and your thread can now cleanup and exit or whatever it needs to do. (Note that to make this work 100% reliably you'll probably want to set your serial-socket to be non-blocking, to ensure that your thread only blocks in select() and never in read())

like image 79
Jeremy Friesner Avatar answered Nov 10 '22 15:11

Jeremy Friesner


You could probably do fake data input:

tty_ioctl(fd,TIOCSTI,"please unblock!");

Before calling it you should set some global flag, in order be able to check after 'read(...)' returns, if received data are just wake up goo or rather something more important.

Source: https://www.systutorials.com/docs/linux/man/4-tty_ioctl/

like image 30
Anonymous Avatar answered Nov 10 '22 16:11

Anonymous


AFAIK signals are the only way to break any thread out of a blocking system call.

Use a pthread_kill() aimed at the thread with a USR1 signal.

like image 4
kja Avatar answered Nov 10 '22 16:11

kja