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);
}