Closed pssaravanan closed 7 years ago
You don't mention which version of ACRA you are using, but if it ios 4.7+ then ACRA will be using the SenderService to send the report in a different process. When that new process is started it is possible that your errant Service is also started.
You should ensure that your service is only started for the non ACRA process.
We using acra 4.8.5. Any code snippet will be useful. Thanks.
Note: I am new to android. I defined a seperate process for running the service by setting android:process for service. But still the problem occurs. And i am starting service with START_STICKY.
How are you starting your service?
By using context.startService(intent).
Yes, but from where and when?
In two places, in the main activity and when phone call received using broadcast receiver.
I put log in different places like where i am starting the service(main activity & phone call receiver), onStartCommand, before error. and i am seeing, service is only once started in MainActivity. And other logs are from onStartCommand method and before error.
It is probably because you are starting your service with START_STICKY. I suspect this is causing your service to attempt to restart each time. Are you sure that's what you want to do?
There were two approches to my problem very similar to truecaller.
I cant go to phone call receiver because, it is delayed by few seconds. which is not surely acceptable for my problem. Hence i choosen service with START_STICKY. Even then, without acra, Services stops after a second try may be.
Thanks,
I was able to reproduce the problem with a service with only this method:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
ACRA.log.d(ACRA.LOG_TAG, "Service started");
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
ACRA.log.d(ACRA.LOG_TAG, "Service crashing");
throw new RuntimeException();
}
}, 100);
return START_STICKY;
}
However I have no idea how to fix this. Of course we could stop all services in the crashing process, but I can't think of any way on how to identify if a Service is responsible for a crash or not.
You could always check ACRA.isACRASenderServiceProcess()
inside onStartCommand()
and refuse to start the service. But I don't see a way of doing it generically.
The service is not restarted inside the acra process. It normally respawns in a process with the same name as the one that got killed, but I also saw it in an unnamed process a few times.
So unless we can find a way of starting the SenderService in a new Process without also starting any STICKY services then we can't support apps with services that use START_STICKY.
To my understanding the trigger for restart is not the start of senderservice, but instead the kill of the process.
The real problem is that all services in the same process will show the same behaviour regardless of their role in the crash.
Is this caused by ACRA explicitly killing the process? If so what happens if we stop doing that?
Yes. If we do not kill the process, all threads but the crashed one will continue to run. While I haven't tested this, I suspect that this will lead to inconsistent states, especially if the crashed thread is the main thread (unless android recreates it).
I'd say it will require a lot of testing. For example I would not expect to see any other activity lifecycle methods being called after I threw an exception in oncreate. But this is what could happen.
Also the default exception handler exits the same way, but I see my service is restarted exactly one time (so two crashes). Maybe we can find out why that is the case and copy the behaviour.
Is this caused by ACRA explicitly killing the process? If so what happens if we stop doing that?
I did my tests. We do not want to stop doing that. If the crashed thread was connected to a Looper (e.g. Main Thread, UI Thread), bad things are happening. I have seen everything from ANR to a System crash depending on the place of the exception.
Right now, i did work around to my problem, by having the code.
Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
ACRA.getErrorReporter().uncaughtException(thread, ex);
Intent in = new Intent(context, ProblematicService.class);
context.stopService(in);
}
});
Thanks
I spent some more time on this. I have to say: There is no nice solution. Options are:
Actually I saw a glimpse of a good solution, but it involves sourcecode/bytecode postprocessing. I have no experience in that whatsoever. Also bytecode manipulation doesn't work with the new jack toolchain atm.
If there was a way in the UncaughtExceptionHandler to determine that this Thread/Process is owned by Service and we can determine what service, then we could use @pssaravanan 's approach generically.
The problem is that Threads and Android components do not correlate in any way. Multiple Services and activities might be using the same main thread, and threads can be shared with bound services. The only way i know of to eliminate this problem is to use a different process for that service, but even in this case we'd need to get a hold on the service instance to prevent the restart.
Edit: We'd need a mapping from process name to service class (not service instance).
What if we stopped all services regardless?
Is an option, but must be opt-in. Most apps will not expect their services to stop outside their own control.
That sounds reasonable to me. New config item: stopServicesOnCrash
A boolean or an array of service classes?
I think Boolean. Keep it simple. Kill all services (except SenderService). After all the app has just crashed.
Resolved in #513
Hi, I have a background service which runs contiously. if crash happened in background service, it is captured by acra, sends report and kills the app. But the background service started again. and crash again and send report again and kills the app again and restart again and it happens continously. And my service getting error report for every seconds. When i check without acra. in a second time, ANR comes and service ended.
Thanks, Saravanan