Hi,

On our caciocavallo-web demo server I sometimes experience endless spinning
in an EventDispatchThread (in run()) which should have been shut down long
ago by AppContext.dispose() - causing our server to consume 100% cpu.

I tried to anylze the situation using a remote debugger, this is what I've
found:

The thread is interrupted, therefor no events are dispatched anymore by
pumpEventsForFilter:

>       while (doDispatch && cond.evaluate()) {
>             if (isInterrupted() || !pumpOneEventForFilters(id)) {
>                 doDispatch = false;
>             }
>         }
>

however, detaching the thread from the EventQueue fails, because there are
still events left for dispatching,
which in turn won't be dispatched, because the thread is interrupted.

1.) A fix would be to check for isInterruped also in the thread's run loop:

    public void run() {
>         while (true) {
>             try {
>                 pumpEvents(new Conditional() {
>                     public boolean evaluate() {
>                         return true;
>                     }
>                 });
>             } finally {
>                 EventQueue eq = getEventQueue();
>                 if (eq.detachDispatchThread(this) || threadDeathCaught ||
> isInterrupted()) {
>                     break;
>                 }
>             }
>         }
>     }
>


What do you think about the proposed solutions?


2.) A big mystery for me was, why the thread hasn't been killed by
Thread.stop(), called by AppContext.dispose() - and why the
"threadDeathCaught"-variable was still false (as this would have caused the
thread to exit anyway).
The reason was, ThreadDeath is swollowed by the IllegalMonitorStateException
caused by Thread.stop():

Basically this is what is going on, when waiting for new events:

 pushPopLock.lock();
        try {
          cond.await(); //Throws ThreadDeath
        }finally {
           pushPopLock.unlock(); //Throws IllegalMonitorStateException,
"swollows" ThreadDeath
        }

So ThreadDeath is never catched.

This bug has been introduced when converting to java.util.concurrent, as
java monitors don't throw an exception in this situation.
My proposal for this bug would be to do away with the
threadDeathCaught-variable completly, as the isInterrupted()-check proposed
in 1.) will stop the thread anyway.

Thanks, Clemens

Reply via email to