[concurrency-interest] backport: unchecked exceptions swallowed by executor service

Joe Bowbeer joe.bowbeer at gmail.com
Tue May 2 20:06:22 EDT 2006


On 5/2/06, Andrew Lentvorski <bsder at allcaps.org> wrote:
>
> I now wrap all code that might let exceptions into Executor/Callables
> like so:

FutureTask can also be thought of as a "captive" Callable.  And
captive Runnable as well (don't forget the unchecked exceptions...).

The standard FutureTask isn't as proactive as your creation when it
comes to reporting the exceptions, though.  It relies on someone to
check the result and deal with the exception at that time.

If you're not checking the results of the task explicitly, the I would
still recommend (even in light of Tom Sugden's message) overriding
done() to handle exceptions proactively.

=> Then, if you want to go one step further, to report exceptions
thrown in done(), for example, you can override the afterExecute
method of the ThreadPoolExecutor.


On 5/2/06, Andrew Lentvorski <bsder at allcaps.org> wrote:
> Tom Sugden wrote:
> > Hi,
> >
> > I was surprised by the behaviour that occurs when an unchecked exception is
> > raised by an overridden implementation of FutureTask#done() method. The
> > exception seems to be swallowed and the executor maintains a user thread for
> > some time afterwards. This isn't causing any problems for me at the moment,
> > but I was just wondering whether it was the intended behaviour? It could be
> > difficult to debug if your done() implementation had a programming error
> > that raised an unchecked exception.
>
> I got burnt by something similar.  The big problem is that you get into
> the habit of assuming that unchecked exceptions will always squawk when
> programming Java.  That fails when you start using concurrent.
>
> I understand *why* they needed to use Exception, but, man, the first
> time you get burnt by a NullPointerException which silently shuts down
> your Callable you pull your hair out.
>
> I now wrap all code that might let exceptions into Executor/Callables
> like so:
>
> >               public Object captiveCall() throws InterruptedException, IOException {
> >                       return obj;
> >               }
> >
> >               public Object call() throws Exception {
> >                       Object retval = null;
> >                       try {
> >                               retval = captiveCall();
> >                       } catch (InterruptedException e) {
> >                               l4j.debug("InterruptedException", e);
> >                               throw e;
> >                       } catch (IOException e) {
> >                               l4j.debug("IOException", e);
> >                               throw e;
> >                       } catch (Exception e) {
> >                               // This normally bad code of catch on Exception is here for a *reason*.
> >                               // Future *eats* all exceptions *silently*.  This clause at least allows
> >                               // the exception to emit noise for debugging.  This is particularly pernicious
> >                               // if you have something like a NullPointerException
> >                               l4j.debug("Exception", e);
> >                               throw e;
> >                       }
> >
> >                       return retval;
> >               }
>
> -a



More information about the Concurrency-interest mailing list