views:

253

answers:

5

I have the following code in a Runnable that gets passed to a thread t:

public void run() {
        logger.debug("Starting thread " + Thread.currentThread());

        try {
            doStuff();
        } catch (Exception e) {
         logger.debug("Exception in Thread " + Thread.currentThread());
        } 

        logger.debug("End of thread " + Thread.currentThread());
    }

I've hit a bug where I see deadlock with the following conditions

  • only the start of thread message has been printed by my logs
  • A thread dump shows that the thread t (supposed to be executing this) is no longer running

Is there some magical way this thread could have terminated early without either logging an end of thread message OR throwing an exception?

A: 

Sure, the thread could get interrupted after the end of the try/catch block but before the last logger.debug statement. In that case it would throw an InterruptedException that, in principle, might not get recorded anywhere (if the default exception handler is set to ignore such things).

That seems like a rather unlikely scenario, though... it's kind of hard to tell what's going on without knowing more about the rest of your program, though.

David Zaslavsky
Assuming interruptible I/O on the logger.
Tom Hawtin - tackline
+6  A: 

Are you sure that doStuff() did not throw an Error? Change catch (Exception e) to catch (Throwable t). It's possible to kill threads in Java with Thread.stop(), but that is highly unlikely.

Esko Luontola
thanks much. Turns out the thread was OOMing -- and since I wasn't catching throwable (and perhaps other logging was misconfigured?), I didn't get any notification
Jacob
+1  A: 

Are you sure that where you start() the Thread, you also join() it afterwards?

Runnable myRunnable=new Runnable(){
  @Override
  public void run(){
    // your original code goes here
  }
};

Thread myThread=new Thread(myRunnable);

myThread.start();

myThread.join(); // magic happens here! it waits for the thread to finish ;)

By the way, join() may throw an InterruptedException, so if something interrupts your thread while it's running, join will inform you about this by throwing this exception.

Hope this helps.

ivan_ivanovich_ivanoff
+1  A: 

When you catch Exception, you will catch any RunnableException and any declared thrown Exception, but you will not catch anything that extends Error. If you truly want to catch anything, then you need to catch Throwable.

If you want to do this for logging purposes only and you don't care why the Thread exits, you can do this:

public void run() {
  logger.debug("Starting thread " + Thread.currentThread());
  try {
    // The work of your Thread
  } finally {
    logger.debug("End of thread " + Thread.currentThread());
  } 
}

and the finally statement is guaranteed to execute unless the Thread is stopped or deadlocks or in some other way stops executing without an Exception.

In most of my programs, I install an UncaughtExceptionHandler so that I'll know about every Thread that dies unexpectedly. It's been a tremendous help in tracking failures. This was added to the language as of Java 5.

Eddie
A: 

When ever you trap a general exception I suggest you log it so you know what the exception was and it cause. Failing to do so will not help you at all.

Peter Lawrey