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.
currentThread(). interrupt() , you set the interrupt flag of the thread, so higher-level interrupt handlers will notice it and can handle it appropriately.
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.
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.
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.
... 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.
Due to the following reasoning:
InterruptedException
MUST NOT be swallowed,
any IOException
(and, in particular, InterruptedIOException
) MAY
be swallowed, that is, consumed by 3rd party code
IOException
is intended to inform about events that happen with i/o, not about changes in the thread status
Some code that we cannot control may either set or clear the thread interrupted status before throwing or re-throwing InterruptedIOException
I decided that:
InterruptedIOException
.InterruptedIOException
SHOULD NOT assume any particular state of the thread interrupted statusthis 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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With