Interrupted exception chaining

R

raphfrk

Is there a recommended way of "chaining" interrupted exceptions?

This is to implement a method call that doesn't throw an interrupted exception, but which calls a method which can be interrupted.

public void uninterruptableWait(Object c) {
boolean done = false;
boolean interrupted = false;
synchronized (c) {
while (!done) {
try {
c.wait();
done = true;
} catch (InterrupedException ie) {
interrupted = true;
}
}
}
if (interrupted) {
Thread.currentThread().interrupt();
}
}

If that interrupt was unexpected, and causes a stack trace, then it would be nice if it could include the details from the thrown exception.

Is there a better way to do the above?
 
E

Eric Sosman

Is there a recommended way of "chaining" interrupted exceptions?

This is to implement a method call that doesn't throw an interrupted exception, but which calls a method which can be interrupted.

public void uninterruptableWait(Object c) {

(Aside: This could probably be a `static' method.)
boolean done = false;
boolean interrupted = false;
synchronized (c) {
while (!done) {
try {
c.wait();
done = true;
} catch (InterrupedException ie) {

(Aside: `InterrupttttttttttttttttttttedException'.)
interrupted = true;
}
}
}
if (interrupted) {
Thread.currentThread().interrupt();
}
}

If that interrupt was unexpected, and causes a stack trace, then it would be nice if it could include the details from the thrown exception.

Is there a better way to do the above?

It seems you're trying to have things both ways: You "expect"
the interrupt by catching it, but then want to consider it as
"unexpected" anyhow. Also, you want to inform your caller but
have chosen not to throw an informative exception.

Since an exception is just an object, I suppose you *could*
have the method return it, or return `null' if there was none:

/**
* Waits for notify() or notifyAll() on an object, in
* spite of interruptions.
* @param c The object to wait for.
* @return {@code null} if no interrupts occurred while
* waiting, or one of the {@code InterruptedException}s
* if one or more were thrown.
*/
public static InterruptedException
uninterruptableWait(Object c) {
InterruptedException ex = null;
for (;;) {
try {
c.wait();
return ex;
} catch (InterruptedException ie) {
ex = ie;
}
}
}

This looks vile to me, though. I think your difficulty is
self-inflicted, and should be solved by rethinking your design.
 
M

markspace

Is there a recommended way of "chaining" interrupted exceptions?


I mostly agree with Eric. You shouldn't suppress interrupts unless you
must. If for example you are implementing a Runnable, you can't throw
InterruptedException but must deal with it somehow. Then catching an
interrupted exception is reasonable.

In this case however it's 100% your code and you could throw
InterruptedException. That would defeat the purpose of the code you
show, of course, but then that is also our point: what you are doing is
rather questionable.

There's no standard pattern for this because it's not done. I'd say the
closest we have to to use a finally block to make certain the interrupt
flag is restored.


/** A questionable method: wait without throwing InterruptedException. */
public void uninterruptableWait(Object c) {
boolean interrupted = false;
try {
synchronized(c) {
for(;;) {
try {
c.wait();
return;
} catch(InterruptedExcpetion ex ) {
interrupted = true;
}
}
}
} finally {
if(interrupted == true ) Thread.currentThread().interrupt();
}
}
If that interrupt was unexpected, and causes a stack trace, then it
would be nice if it could include the details from the thrown
exception.


If you really need the details of the exception but can't throw from
your local use site, I'd say wrapping the exception in a
RuntimeExcpetion and throwing that is best. (Exception don't ever
throwing RuntimeException; subclass it and throw your specific exception.)
 
D

Daniel Pitts

Is there a recommended way of "chaining" interrupted exceptions?

This is to implement a method call that doesn't throw an interrupted exception, but which calls a method which can be interrupted.

public void uninterruptableWait(Object c) {
boolean done = false;
boolean interrupted = false;
synchronized (c) {
while (!done) {
try {
c.wait();
done = true;
} catch (InterrupedException ie) {
interrupted = true;
}
}
}
if (interrupted) {
Thread.currentThread().interrupt();
}
}

If that interrupt was unexpected, and causes a stack trace, then it would be nice if it could include the details from the thrown exception.

Is there a better way to do the above?

To take a pattern from Spring Binding (which may have taken it from
elsewhere), you can keep a list of the caught exceptions, and then at
the end of your method if that list is not empty, throw a new exception
which contains the list.

BTW, the stack-trace will only be on the c.wait() line, since that is
where the interrupted exception will be thrown. This does not help you
know who interrupted you unexpectedly.

Do you really have a use-case for uninterruptableWait? Perhaps you
should instead have a different approach to interrupting that thread.
An interrupt is often a result of a user-action, and ignoring it will
make users mad. It may also be the case that the interrupt was caused
because something else failed, and waiting no longer is useful.

I'd be curious to read your use case. I've written similar code in the
past, and have since realized it was misguided.

Good luck,
Daniel.
 
I

Ivan Ryan

I mostly agree with Eric.  You shouldn't suppress interrupts unless you
must.

Well, the idea is to be able to have a method where the caller doesn't
have to worry about handling interrupts.
If you really need the details of the exception but can't throw from
your local use site, I'd say wrapping the exception in a
RuntimeExcpetion and throwing that is best.  (Exception don't ever
throwing RuntimeException; subclass it and throw your specific exception.)

It was to implement an interface.
https://github.com/SpoutDev/SpoutAP...a/org/spout/api/util/concurrent/SpinLock.java
 
E

Eric Sosman

Well, the idea is to be able to have a method where the caller doesn't
have to worry about handling interrupts.

Fine: The called method handles its own interrupts, and
that's that. But then, the O.P. wants the information about
the interrupt to propagate back to the caller -- the very same
caller that "doesn't have to worry about handling interrupts!"

"Pick a card, any card, don't show it to me. Okay, what
card is it?"
 
M

markspace



This looks 100% bogus to me. First, the JVM will insert spin-locks
where needed in your code automatically. No need to try to build your
own. The first rule of programming is "Don't re-invent the wheel."
(The 0th rule is "Get a deposit with all contracts.")

Second this is exactly the sort of situation where hiding an
InterrruptedException will get you into trouble. Better to just
re-throw and let the calling code deal with the exception (if desired).

But even better to just delete this class and use
java.util.concurrent.locks.ReetrantLock or something similar from the
Java API.

Plus, existing locks are more efficient that you might guess. I don't
think an AtomicBoolean is going to beat them. Look into
AbstractQueuedSynchronizer or LockSupport if you really must implement
your own subclass of Lock.

<http://grepcode.com/file/repository.../util/concurrent/locks/ReentrantLock.java#111>
 
J

Jan Burse

Hi,

Daniel said:
Do you really have a use-case for uninterruptableWait? Perhaps you
should instead have a different approach to interrupting that thread. An
interrupt is often a result of a user-action, and ignoring it will make
users mad. It may also be the case that the interrupt was caused
because something else failed, and waiting no longer is useful.

Since he calls Thread.currentThread().interrupt() the next
wait() will throw an InterruptedException. So it is not
really ignored. It will be only ignored if all of the code
uses uninterruptableWait(), and nowhere Thread.interrupted()
is queried.

Is there a better way to do the above?

But the biggest flaw I see in the original code, is that
done=true is not called in the exception handler, so it will
not break out of the code. Actually it will inflict a new
InterruptedException by the wait() and so on.

(Erics and marks code have a similar flaw, the flaw there
is that wait() is again called, so code could block)

Probably the code is only working, since wait()s are allowed
to be spurious. But if this is not happening the CPU will
burn, burn, burn, ...

Bye
 
M

markspace

(Erics and marks code have a similar flaw, the flaw there
is that wait() is again called, so code could block)


That's actually a fair point. "Doesn't throw" isn't the same as
"ignore." However, ReentrantLock is probably still better than the
following code.


/** A questionable method: wait without throwing InterruptedException. */
public void uninterruptableWait(Object c) {
boolean interrupted = false;
try {
synchronized(c) {
try {
c.wait();
return;
} catch(InterruptedExcpetion ex ) {
interrupted = true;
}
}
} finally {
if(interrupted == true ) Thread.currentThread().interrupt();
}
}
 
J

Jan Burse

Hi,

Anyway the code that will notify c should also set some state.
If it doesn't we cannot distinguish between a spurious wait (*) and
a wait by a notify. So code must use a loop, and to not confuse
the done flag and loop breaking, we can just shift the try/catch
outside of the loop, and even outside of the synchronized to
minimize the monitor region:

public boolean done; /* should be set by the thread that
notifies the lock */
public Object lock = new Object();

public void uninterruptedWait() {
try {
synchronized(lock) {
while (!done)
lock.wait();
}
} catch (InterruptedException x) {
Thread.currentThread().interrupt();
}
}


(*)
The doc mentions it explicitly:

As in the one argument version, interrupts and *spurious wakeups* are
possible, and this method should always be used in a *loop*:
http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait()

Bye
 
J

Jan Burse

Jan said:
If it doesn't we cannot distinguish between a spurious wait (*) and
a wait by a notify.

Corr.:
If it doesn't we cannot distinguish between a spurious wakeup (*) and
a wakeup by a notify.

This is how the notify should be done, it needs also to
use a synchronized():

public void signalDone() {
synchronized(lock) {
done=true;
lock.notifyAll();
}
}

I prefer using notifyAll() from the beginning, since the condition
that is signaled can get more and more complex over the time, and
it might be that some threads will or will not react to it, so that
notify() might pick one which will not react, and then the signal
is spurious.

Bye
 
M

markspace

Hi,

Anyway the code that will notify c should also set some state.
If it doesn't we cannot distinguish between a spurious wait (*) and
a wait by a notify. So code must use a loop, and to not confuse
the done flag and loop breaking, we can just shift the try/catch
outside of the loop, and even outside of the synchronized to
minimize the monitor region:

public boolean done; /* should be set by the thread that
notifies the lock */


While I agree this works in some cases, I don't think it works for the
OP. He's trying to simulate a spin lock, by extending the Lock
interface. "done" is signaled by calling unlock() on that interface.

I don't see how that can be done reliably.

public class SpinLock implements Lock {
private volatile boolean done;
private final Object lock = new Object();

public void lock() {
// ignore the "spin lock" for now
try {
synchronized( lock ) {
while( !done ) lock.wait();
}
} catch( InterruptedException ex ) {
Thread.currentThread().interrupt();
}
// how does "done" get reset?
}

public void unlock() {
synchronized( lock ) {
done = true;
lock.notify();
}
}
}

I don't see how "done" can be reliably reset. There's going to be a
race condition somewhere. Might as well use ReetrantLock, it solves
this problem.

(You can solve it too, but you're basically cutting and pasting code
from ReetrantLock at that point. Easier to just reuse code.)
 
J

Jan Burse

markspace said:
While I agree this works in some cases,

Just replace done by the <cond> you want to anyway check.
The main point is that you cannot go, since factoring
out the programming pattern works not:


synchronized (c) {
while (!<cond>)
uninterruptableWait(c);
}


But rather simply apply the programming pattern:

try {
synchronized (c) {
while (!<cond>)
c.wait();
}
} catch( InterruptedException ex ) {
Thread.currentThread().interrupt();
}

Or if you want to scare the hell out of your clients, use:

public interface Predicate {
public boolean _true(Object c);
}

public void uninterruptableWait(Object c, Predicate p) {
try {
synchronized (c) {
while (!p._true(c))
c.wait();
}
} catch( InterruptedException ex ) {
Thread.currentThread().interrupt();
}
}

Then what you call "SpinLock", but what I would call
"OneTimeLock". Can be implemented as follows:

public void waitDone() {
uninterruptableWait(lock,new Predicate() {
return done;
});
}

Of course you can turn a "OneTimeLock" into a "ManyTimeLock",
for example. You can reset the done inside the synchronized
of the waitDone(). The synchronized will assure that when
you leave the synchronized the done=false holds, since no
other thread will interfer while inside the synchronized
and after the wait():

public void waitDone() {
try {
synchronized( lock ) {
while( !done )
lock.wait();
done=false;
}
} catch( InterruptedException ex ) {
Thread.currentThread().interrupt();
}
}

To abstract this pattern we would need:


public interface Predicate {
public boolean _true(Object c);
}

public interface Action{
public boolean perform(Object c);
}

public void uninterruptableWait(Object c, Predicate p, Action a) {
try {
synchronized (c) {
while (!p._true(c))
c.wait();
a.perform(c);
}
} catch( InterruptedException ex ) {
Thread.currentThread().interrupt();
}
}

And one can then do:

public void waitDone() {
uninterruptableWait(lock,new Predicate() {
return done;
}, new Action() {
done=false;
});
}

Eagerly avaiting JDK 7 lambdas...

Bye
 
J

Jan Burse

Jan said:
public void waitDone() {
uninterruptableWait(lock,new Predicate() {
return done;
}, new Action() {
done=false;
});
}

Eagerly avaiting JDK 7 lambdas...

You see, I didn't write it right, it is of course:


public void waitDone() {
uninterruptableWait(lock,new Predicate() {
public _true(Object c) {
return done;
}
}, new Action() {
public perform(Object c) {
done=false;
}
});
}

So since there are not yet lambdas, we have to
write the method names of the interfaces. But
JDK 8 lambdas would exactly do this for us,
fill in the blanks. Sadly I don't currently
find the blog by John Rose that explains it.

Bye
 
J

Jan Burse

Jan said:
Hi,


Do you refer to:

Condition.awaitUninterruptibly() ?
http://docs.oracle.com/javase/1.5.0...t/locks/Condition.html#awaitUninterruptibly()


Didn't look yet at the source. What is the design?

Bye

I guess if we were to allow to introduce a data structure
Condition or so, we could also do the same. Provide an
uninterruptableWait on this Condition. So we would again
divert from the original:

public static void uninterruptableWait(Object c);

And either have:

public static void uninterruptableWait(Condition c);

Or:

public class Condition;
public void uninterruptableWait();

Simplest datastructure would be:

public class Condition {
public Object lock = new Object();
public boolean done;
}

Bye
 
J

Jan Burse

But the programming pattern for awaitUninterruptibly() would
be different from uninterruptableWait(). Since the spec says
that spurious wakeups are still posible. So I guess something
along:

while (!(flag=Thread.interrupted()) && !<cond>)
awaitUninterruptibly();
if (!flag)
<action>
} else {
Thread.currentThread().interrupt();
}

Ugly
 
M

markspace



Truly! And it only took you eight replies, mostly to your own posts, to
arrive at that idea. I think I mentioned ReetrantLock up thread? And
you should look at the source of that class, it's very interesting.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,812
Latest member
GracielaWa

Latest Threads

Top