1

I want the user to be able to send an error report when my service crashes. I have an GUI app which gets updated using broadcasts from the service. The service runs in a different process and runs as foreground. I used the same code to attach the default exception handler to my GUI and there it works fine (opens the e-mail send app and the body of the e-mail contains the exception). But for my service threads, I cannot get them to call the UncaughtExceptionHandler.

The research I did so far is that the thread that crashes has a different threadid (12) than the thread I registered the cutom exceptionhandler on (229) The registration and the crash are in the same Timer_Tick runnable and should have the same threadid.

Logcat output:

> D/Registratie: General exception handler set for threadid=229 
> D/Registratie: ThreadName in Timer_Tick: Timer-0 threadId=229
> D/Registratie: ThreadName in Timer_Tick: Timer-0 threadId=229
> D/Registratie: ThreadName in Timer_Tick: Timer-0 threadId=229
> D/Registratie: Throw ArrayIndexOutOfBounds exception W/dalvikvm:
> threadid=12: thread exiting with uncaught exception (group=0x4169fba8)

Service member and method:

// declared non-anonymous to prevent the garbage collector erroneously clearing
private Thread.UncaughtExceptionHandler mUEHandler; 


public void attachGeneralExceptionHandler(){

        mUEHandler = new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                Log.d(TAG, "Custom crash handler: build crashrapport and intent");
                sendExceptionReport(t,e);

                mUEHandler.uncaughtException(t, e);

            }
        };

        Thread.setDefaultUncaughtExceptionHandler(mUEHandler);
        Log.d(TAG, "General exception handler set for ThreadName: " + Thread.currentThread().getName() + " threadid=" + Thread.currentThread().getId());

    }

TimerTick from the service:

private Runnable Timer_Tick = new Runnable() {
        public void run() {

            if(!uncaughtExceptionHandlerSet) {
                // Make sure the exception handler is connected to this Timer_Tick thread
                attachGeneralExceptionHandler();
                uncaughtExceptionHandlerSet=true;
            }
            Log.d(TAG, "ThreadName in Timer_Tick: "+ Thread.currentThread().getName()+" threadId="+Thread.currentThread().getId());

            if(testExceptionHandling){
                Log.d("TAG", "Throw ArrayIndexOutOfBounds exception");
                int[] exceptionTest = new int[3];
                exceptionTest[3] = -1; // throws exception on thread with threadid 12, only one line in logcat

            }
}
Harmen
  • 841
  • 8
  • 17
  • just call `Thread.setDefaultUncaughtExceptionHandler()` inside `Application#onCreate`, (you need to extend `Application` class) – pskink Feb 02 '16 at 17:58

1 Answers1

0

The documentation for Thread.setDefaultUncaughtExceptionHandler() indicates:

This handler is invoked in case any Thread dies due to an unhandled exception

You don't need to call that method for each thread. Try setting the default handle in the onCreate() method of your service.

Bob Snyder
  • 37,759
  • 6
  • 111
  • 158
  • Yes, that is what I had in the first try. That doesn't work either. I figured that it didn't work because the onCreate might be an OS thread (I could not find in the documentation what thread invokes the onCreate method). – Harmen Feb 02 '16 at 16:04
  • Hmmm. I'll research more. I thought "any" meant every thread in the process. – Bob Snyder Feb 02 '16 at 16:08
  • Yes, I think your interpretation of the documentation is right. It doesn't help my problem though. The weird thing is that I don't get a stack dump in the logcat anymore. – Harmen Feb 02 '16 at 16:09
  • I'm wondering about this statement `mUEHandler.uncaughtException(t, e);` in `mUEHandler`. Isn't that recursive? Was your intention to propagate the exception to the previous default handler? – Bob Snyder Feb 02 '16 at 16:26
  • 1
    FWIW--For one of my apps, I implemented a default handler in an Application subclass similar to what is described [here](http://stackoverflow.com/questions/19897628/need-to-handle-uncaught-exception-and-send-log-file). I just tested and confirmed that this approach catches exceptions in worker threads in a service, both when the app is a single process and when the service is in a separate process. – Bob Snyder Feb 02 '16 at 17:31
  • Thanks for thinking along qbix! The calling of uncaughtException was indeed meant to propagate the exception to the previous default handler (found it somewhere). When I remove that statement there is no change of behavior (as expected since the crash-report e-mail isn't build either). I'll take a thorough look at your solution. – Harmen Feb 02 '16 at 19:31