Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I do `Thread.currentThread().interrupt()` before `throw new InterruptedIOException()`?

I implement MyInputStream.read() and notice that an InterruptedException may happen within this function. After some searching I have found that it is common to catch the InterruptedException and re-throw an InterruptedIOException, something like:

    try {
        ...
    } catch (InterruptedException e) {
        //Thread.currentThread().interrupt(); // <=== ???
        throw new InterruptedIOException();
    }

but only about 50% of code samples do Thread.currentThread().interrupt(). Well, it is agreed that the worst thing you can do with InterruptedException is swallow it, but should I reinterrupt the current thread before throwing a different exception?

PRO: a single interruption request may have multiple "recipients."

CONTRA: some functionality like logging may be not working before the interrupt status is cleared, which may cause subtle bugs.

CONTRA: we get two notifications about the interrupt request: the thread's interrupted status and the exception. Initially, there is only one notification: either the thread's interrupted status is true or an InterruptedException is thrown, but not both.

PRO: nobody really tests the code against i/o exceptions that may be thrown, and the InterruptedIOException is different from other i/o exceptions; a catch(IOException) clause may swallow the interrupted status.

PS It looks like whatever I do, the problem that InterruptedIOException is a very special kind of IOException requiring a special handler will not be solved.

PPS (EDIT) I cannot let the original InterruptedException propagate because InputStream.read() cannot throw InterruptedException (it throws IOException and does not throw anything else). And I cannot predict the context in which MyInputStream.read() will be called: an instance of MyInputStream may be passed to any Java or 3rd-party library function that takes an InputStream argument.

As to the old bug, it looks like it was just closed, not fixed; and the very idea of the interrupted status is that the code would behave differently.

like image 435
18446744073709551615 Avatar asked Nov 17 '15 12:11

18446744073709551615


People also ask

What is the use of thread currentThread () interrupt ()?

currentThread(). interrupt() , you set the interrupt flag of the thread, so higher-level interrupt handlers will notice it and can handle it appropriately.

When should we interrupt a thread?

An interrupt is an indication to a thread that it should stop what it is doing and do something else. It's up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate.

What happens if the current thread has interrupted by another thread in thread interrupted exception?

In this state, a thread is waiting for a signal from another thread. When a thread either finishes execution or terminates abnormally, it'll wind up in the TERMINATED state. Threads can be interrupted, and when a thread is interrupted, it will throw InterruptedException.

Why InterruptedException should not be ignored?

If there is any scenario when an unwanted interrupt to your thread can leave System or any resource in unwanted state (dirty, locked, not released which can cause leaking resource) then its your responsibility to handle the InterruptedException and you should not ignore it.


3 Answers

... should I reinterrupt the current thread before throwing a different exception?

If something upstack is going to examine the interrupt flag, then yes. Otherwise, it doesn't matter.

CONTRA: some functionality like logging may be not working before the interrupt status is cleared, which may cause subtle bugs.

By my reading of the analysis, the bug you linked to only applies to Java 6 and earlier, and only for the Solaris platform. You can probably discount it now. (Unless you have a customer with deeeep pockets, you should not be doing significant application for Java 6 or earlier.)

CONTRA: we get two notifications about the interrupt request: the thread's interrupted status and the exception.

They are qualitatively different kinds of notification ...

PS It looks like whatever I do, the problem that InterruptedIOException is a very special kind of IOException requiring a special handler will not be solved.

In fact, a better strategy might be to set the interrupted flag in the catch for the InterruptedIOException ... or simply allow the original Interrupted exception to propagate.

like image 190
Stephen C Avatar answered Oct 07 '22 16:10

Stephen C


Due to the following reasoning:

  1. InterruptedException MUST NOT be swallowed,

  2. any IOException (and, in particular, InterruptedIOException) MAY be swallowed, that is, consumed by 3rd party code

  3. IOException is intended to inform about events that happen with i/o, not about changes in the thread status

  4. Some code that we cannot control may either set or clear the thread interrupted status before throwing or re-throwing InterruptedIOException

I decided that:

  1. the current thread MUST be reinterrupted before throwing an InterruptedIOException.
  2. the code handling InterruptedIOException SHOULD NOT assume any particular state of the thread interrupted status
  3. this behavior MUST be documented:

    @throws InterruptedIOException if the current thread is interrupted (the thread
            interrupted status is true when InterruptedIOException is thrown)
    @throws IOException if this stream is closed or another IOException occurs.
    
    Note that due to possible interference from 3rd-party code, handlers 
    of InterruptedIOException should not assume any particular state
    of the thread interrupted status when they are invoked.
    
like image 45
18446744073709551615 Avatar answered Oct 07 '22 18:10

18446744073709551615


I suggest throwing a ClosedByInterruptException. Although it belongs to the NIO library, it has a better defined API than the old InterruptedIOException, making it easier to handle. For example:

try {
    ...
} catch (InterruptedException e) {
    close(); // obeying API of ClosedByInterruptException
    Thread.currentThread().interrupt(); // again, obeying API
    throw new ClosedByInterruptException();
}

See also Thread#interrupt(). If instead you want to re-throw the original exception, you can use:

try {
    ...
} catch (InterruptedException e) {
    throw e;
}

So you keep the stack trace. The interrupt status is left clear in this case, as the API for InterruptedException suggests.

like image 32
muued Avatar answered Oct 07 '22 16:10

muued