Aborting a Blocking Read on Linux

aborting a blocking read on linux

If you only want the signal to affect the read, use pthread_sigmask() to keep the signal blocked until just before the read and to block it again afterwards.

Terminating blocking IO in Linux C++

read() should not leak memory. With both blocking and nonblocking reads, the application code is still responsible for the management of the memory provided as the buf argument. Interrupting read() via a signal will not throw an exception, so if use signals, you will need to check the result and errno.

  • If read() is interrupted by a signal before reading data, -1 will be returned with errno set to EINTR.
  • If read() is interrupted by a signal after reading some data, POSIX allows for either -1 to be returned with errno set to EINTR, or for read() to return the number of bytes already read.

If you use pthread_cancel() then an exception will be thrown. With this approach, you have the following options:

  • Perform cleanup by registering cleanup functions with pthread_cleanup_push().
  • Allocate dynamic memory, storing into thread specific storage via pthread_setspecific().
  • Manage the memory via an auto_ptr/unique_ptr.
  • Catch the abi::__forced_unwind exception, perform cleanup, and rethrow.

In general, consider avoiding thread cancellation. When possible, it is better, and more manageable, to have a shared flag that is used to break out of the loop. This allows the thread to perform any necessary cleanup, and prevents your implementation from being dependent on your threading library's implementation and any of its quirks.

For your case, where you are using a blocking read, consider polling the fd to see if data is available via select() with a timeout, and only call read() if the fd has data. This allows you to periodically check if the thread flag is set to no longer run, and prevents you from needing to deal with signals to interrupt the thread from read(), as read() should no longer block waiting on data.

Also, the behavior that occurs when deleting a thread object is dependent on the thread library. For example, deleting a pthread_t or boost::thread has no effect on the associated thread's execution.

Linux, cancel blocking read()

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())

Abort a read() from another thread

Use pthread_kill() on the thread you want to signal. Don't use kill(); for that matter, since you linked to it, don't use signal() -- it's one of the more retarded, non-portable interfaces:

The behavior of signal() varies across UNIX versions, and has also
varied historically across different versions of Linux. Avoid its
use: use sigaction(2) instead. See Portability below."

[ This has been answered in the comments, but for some reason still shows up in the relevance top of unanswered questions. So here, for the sake of completeness ]

How to stop Linux read system call from blocking?

call

fcntl(fd, F_SETFL, flags | O_NONBLOCK);

This will make the file descriptor non-blocking.

C: blocking read should return, if filedescriptor is deleted

The code you are describing has an inherent race condition - if another thread could be a in blocking read() on a file descriptor when you close() that file descriptor, the other thread could just as well be just about to call read() instead.

You can't call close() unless you know that all other threads are no longer in a position to be using that file descriptor at all.

The easiest way to handle cases like you describe is for one thread to be the 'owning' thread of each file descriptor, that is responsible for closing the file descriptor. Other threads don't directly close it - instead they mark the file descriptor as "to be closed" in some shared data structure and wake up the owning thread.

You can make it possible to wake the owning thread by having it not block in read() but instead block in select() or poll() with another file descriptor - usually a pipe - in the set as well as the target file descriptor. The thread is woken by writing to the other end of that pipe.

How to abort a blocking process.getInputStream().read() with close()?

You tried close() and it doesn't work. The only other thing I can think of to try is calling Thread.interrupt() on the blocked thread ... but I doubt that that will work either.

The real issue is that the specs (i.e. respective javadocs) don't say whether these things will work. Even if they do work ... for some version of Java on some OS platform ... there is no guarantee that they will work on other version/platform combinations.

Trying to exit from a blocking UDP socket read

This really depends on what system you're running under. For example, if you're running under a POSIX-compliant system and your thread is cancelable, the recv() call will be interrupted when you cancel the thread since it's a cancel point.

If you're using an older socket implementation, you could set a signal handler for your thread for something like SIGUSR1 and hope nobody else wanted it and signal, since recv() will interrupt on a signal. Your best option is not to block, if at all possible.

How to make Bash's read abort after trapping interrupt?

Seems like not interrupting immediately is a Bash non-POSIX extension (see read_builtin in read.def of Bash builtin source (look for posixly_correct)).

You can override this behavior, and exit on the first Ctrl+C by forcing POSIX behavior for read (by setting the POSIXLY_CORRECT environment variable):

#!/bin/bash
trap 'echo $$ was interrupted' INT
POSIXLY_CORRECT=1 read foo
echo done


Related Topics



Leave a reply



Submit