Re: Catching NPEs



Arne Vajhøj wrote:
It is usually consider bad practice to present
a stack trace to the end user.

If the application has state in memory that needs to be
persisted it is a very good idea to save the data
before exiting.

If it is a server type application it would be a good idea
to either just terminate one thread and let the other threads
continue serving their clients or at least restart the entire
server app.

I think that in most real world applications you would catch
that kind of exceptions.

I have developed an app along these lines. There's a FooThread class and a FooThreadFactory, constructors and other methods, and stuff like:

public void run () {
try {
some stuff
} catch (RuntimeException e) {
factory.notifyThreadDeath(this, e);
throw e;
} catch (OutOfMemoryError e) {
app.saveStuff();
factory.shutDown();
factory.notifyThreadDeath(this, e);
throw e;
} catch (Error e) {
factory.notifyThreadDeath(this, e);
throw e;
}
}

Unexpected exceptions are caught and rethrown. Anything other than OOME results in the thread factory being notified via a notifyThreadDeath(FooThread, Throwable) method. This logs the stack trace and decrements a thread count. Elsewhere the factory has a periodically-called method to interrupt or start threads as need be, based on a desired number (depending on the number of requests occurring) and the actual number. (It also keeps a collection of the actual thread objects, so it can pick some at random to interrupt. The stuff in the try block involves taking a request off a blocking queue and handling it in an endless while loop. There's a try that catches InterruptedExceptions and breaks the while loop, also calling factory.notifyThreadDeath(this, null).

Upshot: stack traces are logged so things can be debugged. Request servicing continues, and doesn't even diminish in capacity since the thread that dies is recreated immediately unless it's no longer needed anyway. The code that loops the factory's thread-management method periodically just does so and sleeps, and doesn't do anything that's at all exception prone itself (it doesn't new anything, for instance, except thread objects when necessary). OOME causes it to save some data (mostly caches) and shut down gracefully. (I note that even though the total megabytage of live objects should remain bounded, it does eventually slow down and then catch OOME if it runs a long time. Heap fragmentation?) Restarting the process if it dies somehow is handled externally. Since it's a network using app, most exceptions are I/O exceptions that get handled closer to the source, usually by sending the client an error message and moving on to the next request; they tend to indicate a problem with connectivity or the client having sent a bad or malformed request that includes a bogus URL, parse error, or similarly. Still, the odd wackiness trickles up from time to time. I've had library code randomly bubble up NPEs and various IndexOutOfBoundsException flavours, for example, on rare occasions. Lately (since the deployment environment switched to the Java 6 beta runtime environment) there've been NPEs coming out of Sun code we can't explain (mainly from one particular PriorityQueue deep in the bowels of the app -- I found an "in progress, bug" bug on Sun's site about this one, where someone had it occur with a comparator not consistent with the objects' equals method, which is the case in my code also. A quick check of this newsgroup turns up a complaint of something similar again.) The app recovers from all of these insults with maybe one in ten thousand requests ending up incompletely processed. The transaction gets rolled back, but transactions are pretty much independent of each other, and client requests that are well-formed but get a "temporary service error" message are resubmitted by the client after a backoff delay anyway.
.



Relevant Pages

  • RE: EIF: minimal runtime sys permissions (not related to installutil)
    ... If there is an active request trace then ... EIF automatically also raises through the associated RequestEventSource. ... 'throw' any exceptions in EIF are not caught and bubble up into the ... instrumented app. ...
    (microsoft.public.vsnet.enterprise.tools)
  • Re: How to create an immortal web app?
    ... just as the Session times out. ... after the last request from *any* client. ... I hold the app in memory using Application variables. ...
    (microsoft.public.dotnet.framework.aspnet)
  • Re: Adding Headers in ASP.NET on vista
    ... request from your client, and I'm not sure why you would want to, and ... but not the request. ... I am using an HTTPModule to analyze incoming urls and pass a variable ... I need to pass that ID along to my app. ...
    (microsoft.public.dotnet.framework.aspnet)
  • Remote control with TcpListener
    ... so that if a client connects to it, he can obtain information about application state and to send some commands. ... I started with using TcpListener in a separate thread of the app. ... The idea how i see it should be this: client connects, sends a request, listener responds, then client sends another request, server responds, and so on. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: breaking the model
    ... > The forms data then is in the Request object. ... HTTP Request; in this case, the form POST Request from the Page. ... client and server. ...
    (microsoft.public.dotnet.framework.aspnet)