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
}
}
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.
Related
I'm wondering how to log information when a server has successfully started. I cannot do this as simple as that:
createServer().start(Exit.NEVER);
System.out.println("Server is running...");
because the instruction createServer().start(Exit.NEVER) doesn't return back. This is a call to external library that uses a method with a loop similar to while(true).
I cannot also run the server in a new thread and then log information about successful start because the server may throw exception and hence there was a failure.
public void start () {
new Thread("Server") {
#Override
public void run() {
try {
createServer().start(Exit.NEVER);
} catch (final IOException e) {
throw new UncheckedIOException(e);
}
}
}.start();
System.out.println("Server is running...");
}
Last solution I can think of is to wait a couple of second after createServer().start(Exit.NEVER) and then log the successful start as there was no exception thrown. This is not a perfect solution as we can wait for example 5 seconds and the log the successful start but one second later the server may throw exception.
How do I then can tell whether the server has started successfully and hence log this information?
EDIT
The server I'm using is Takes https://github.com/yegor256/takes.
I have successfully made outgoing call via PJSIP. Now facing a problem while try to handle incoming call.
Thread isanycall=new Thread(new Runnable() {
#Override
public void run() {
while(true)
{
if(Global.isanycall==1)
{
sipOperationIncoming(username, pwd, ip, number.getText().toString());
Global.isanycall=0;
}
}
}
});
isanycall.start();
This code is checking if there is any incoming call.
System.out.println("Incoming call handler");
//sip operation started
registration=SipRegistration.getSipRegistration(uname,pwd,ip);
registration.answerCall(da);
//sip operation ended
This code block is just responsible to call a function answerCall which is as follow
public void answerCall(DialerActivity activity){
call=new MyCall(myacc,1,this.ep,activity);
CallOpParam prm = new CallOpParam();
prm.setStatusCode(pjsip_status_code.PJSIP_SC_RINGING);
try {
call.answer(prm);
}catch(Exception e){
e.printStackTrace();
}
}
Now the exception I am getting is
java.lang.Exception: Title: pjsua_call_answer2(id, param.p_opt, prm.statusCode, param.p_reason, param.p_msg_data)
10-27 12:11:19.839 10090-10384/com.skyteloutsourcing.callnxt W/System.err: Code: 171140
10-27 12:11:19.839 10090-10384/com.skyteloutsourcing.callnxt W/System.err: Description: INVITE session already terminated (PJSIP_ESESSIONTERMINATED)
What can be the reason?
Solved it, I was responding with a different call id rather than which was the call id of incoming call. :)
I faced this error when I don't check this control
if(ci.state==pjsip_inv_state.PJSIP_INV_STATE_DISCONNECTED){
currentCall.delete()
currentCall=null
}
When an uncaught exception occurs on the server, the client has the onFailure() method called on the async callback for the service call. He only gets StatusCodeExceptions, which provide little information. I would like to get the actual exception that occurred on the server with its stack trace. Is this possible in GWT?
In my service interface, I added 'throws Exception' to the methods where I want the exception details from the server. This permits me to get the Exception message that occurred on the server, but its stack trace still stops at the client.
I understand that this is not good practice for a production environment, but I would like to enable this for testing.
This will be a three step process.
Set the uncaught exception Handler. In the onModuleLoad() method should be fine.
GWT.setUncaughtExceptionHandler(new ExceptionHandler());
Create a class that will implement the GWT.UncaughtExceptionHandler interface and will parse the Throwable.
public static class ExceptionHandler implements GWT.UncaughtExceptionHandler {
#Override
public void onUncaughtException(final Throwable e) {
if (e instanceof UmbrellaException) {
final UmbrellaException umb = (UmbrellaException) e;
String errMsg = "";
for (Throwable t : umb.getCauses()) {
errMsg += t.getMessage() + "\n";
for (StackTraceElement element : t.getStackTrace()) {
errMsg += element.getClassName() + "(" + element.getMethodName() + ":"
+ element.getLineNumber() + ")\n";
}
/* errMsg String contains full stack trace */
}
}
}
}
Call the ExceltionHandler and pass in the Throwable that came in the onFailure maithod()
new ExceptionHandler().onUncaughtException(caught);
If any exception occurs on the server simply throw the exception object to the client (from the RPC servlet)
I'm tearing my hair out with this one! I'm a newbie to Android so I'm sure it's something super obvious.
I'm getting a ScheduledThreadPoolExecutor exception where cause: null
All I want is a seperate thread that runs whenever the activity is on screen!
// Instance Variables
private ScheduledExecutorService m_oScheduledExecutor = null;
#Override
protected void onResume()
{
super.onResume();
if (oScheduledExecutor == null)
{
oScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
}
try
{
oScheduledExecutor.scheduleAtFixedRate({Runnable Instance HERE}, 0, 10, TimeUnit.SECONDS);
}
catch (Exception e)
{
System.out.println("(MainActivity) Error: " + e.getMessage() + " Cause: " + e.getCause());
}
}
#Override
protected void onStop()
{
super.onStop();
m_oScheduledExecutor.shutdown();
}
EDIT: Entire Stack Trace....
java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask#41976688 rejected from java.util.concurrent.ScheduledThreadPoolExecutor#4195c7f8[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 1]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1979)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:786)
at java.util.concurrent.ScheduledThreadPoolExecutor.delayedExecute(ScheduledThreadPoolExecutor.java:300)
at java.util.concurrent.ScheduledThreadPoolExecutor.scheduleAtFixedRate(ScheduledThreadPoolExecutor.java:545)
at java.util.concurrent.Executors$DelegatedScheduledExecutorService.scheduleAtFixedRate(Executors.java:619)
at com.example.wifitest.MainActivity.onResume(MainActivity.java:61)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1185)
at android.app.Activity.performResume(Activity.java:5182)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2732)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2771)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1276)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5041)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
You cannot 'recycle' an ExecutorService. Once you have invoked shutdown(), attempting to schedule any task will cause a rejection, and in your case the rejection policy is to throw RejectedExecutionException.
If you follow your stacktrace, you can see in ScheduledThreadPoolExecutor:
/**
* Specialized variant of ThreadPoolExecutor.execute for delayed tasks.
*/
private void delayedExecute(Runnable command) {
if (isShutdown()) {
reject(command);
return;
}
// ...
}
Keeping your executor service as an instance variable is not going to work for you here: once it's been shutdown, it can't be used again.
Do not shutdown the ScheduledExecutorService inside onStop() method. Try to put it inside onDestroy() method. When your activity goes in background, onStop() method might be getting called, as your activity is not visible in the background. Because of this, if the ScheduledExecutorService is shutdown, you might be getting this error.
I'm using 3rd party library for doing some work in my application. Unfortunately, some bugs were found in it and they cause very sad result: my app is hanging as worker thread probably infinite looping. I've read some questions about killing the thread in android VM but they are didn't help me because of:
stop() method is deprecated and not supported bu Andriod VM
interrupt() method doesn't do anything, i mean thread is still alive
The worst thing is that from some moment of time this worker thread starts to use a lot of memory causing GC to run too often which also is not good for app.
I've found some conditions when bug in library is occurred but i there are may be other bugs which i also want to avoid in my app.
Here is ode snippet that shows the problem:
final MutableObject<Object> calculationResult = new MutableObject<Object>(null);
final MutableObject<EvalError> exception = new MutableObject<EvalError>(null);
final MutableObject<Thread> calculationThread = new MutableObject<Thread>(null);
final CountDownLatch latch = new CountDownLatch(1);
new Thread(new Runnable() {
#Override
public void run() {
final Thread thread = Thread.currentThread();
try {
Log.d(CalculatorEngine.class.getName(), "Calculation thread started work: " + thread.getName());
calculationThread.setObject(thread);
calculationResult.setObject(interpreter.eval(jsclExpression));
} catch (EvalError evalError) {
exception.setObject(evalError);
} finally {
Log.d(CalculatorEngine.class.getName(), "Calculation thread ended work: " + thread.getName());
calculationThread.setObject(null);
latch.countDown();
}
}
}).start();
try {
Log.d(CalculatorEngine.class.getName(), "Main thread is waiting: " + Thread.currentThread().getName());
latch.await(4, TimeUnit.SECONDS);
Log.d(CalculatorEngine.class.getName(), "Main thread got up: " + Thread.currentThread().getName());
final EvalError evalErrorLocal = exception.getObject();
final Object calculationResultLocal = calculationResult.getObject();
final Thread calculationThreadLocal = calculationThread.getObject();
if (calculationThreadLocal != null) {
// todo serso: interrupt doesn't stop the thread but it MUST be killed
calculationThreadLocal.interrupt();
resetInterpreter();
}
if ( evalErrorLocal != null ) {
throw evalErrorLocal;
}
if ( calculationResultLocal == null ) {
tooLongExecutionCache.add(jsclExpression);
throw new ParseException("Too long calculation for: " + jsclExpression);
}
} catch (InterruptedException e) {
throw new ParseException(e);
}
Thread could not be killed in davlik:
I used solution proposed by AVD and just set the priority of thread to lowest possible value and invoke interrupt() method.
System.exit() might at least kill your application, if you can detect that the task has stopped responding.