You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Feb 26, 2023. It is now read-only.
First of all, this issue only happens when running robolectric test because I override the Executor, but it can happen in production if tasks are executed too fast.
I have the following executor, that simple execute tasks in serial for test purpose:
public class UIThreadExecutor implements Executor{
@Override
public void execute(@NonNull Runnable command) {
try {
command.run();
}catch (Exception ignored){
}
}
}
And I have the follow test:
@Test
public void testSerial(){
BackgroundExecutor.setExecutor(new UIThreadExecutor());
for (int i = 0; i < 10; i++){
activity.testSerial();
}
await().atMost(10, TimeUnit.SECONDS).until(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return activity.count == 10;
}
});
}
The activity testSerial implementation is:
public static int count = 0;
@Background(serial = "test")
public void testSerial(){
count++;
System.out.println("count = " + count);
}
If you run this test, it will cause dead lock. Digging in the code I was able find out why.
As you see the task is add after the directExecute is called. Let's take a look at the Task clean post executed code:
private void postExecute() {
if (id == null && serial == null) {
/* nothing to do */
return;
}
CURRENT_SERIAL.set(null);
synchronized (BackgroundExecutor.class) {
/* execution complete */
TASKS.remove(this);
if (serial != null) {
Task next = take(serial);
if (next != null) {
if (next.remainingDelay != 0) {
/* the delay may not have elapsed yet */
next.remainingDelay = Math.max(0L, targetTimeMillis - System.currentTimeMillis());
}
/* a task having the same serial was queued, execute it */
BackgroundExecutor.execute(next);
}
}
}
}
As you see in this code we remove the task after the execution, but my execution always finish before the Task is added to the stack. Causing a dead lock, because the task is added to to list and never removed.
One possible solution would be simple check if the task is already finished (managed) before add it to the list: if ( (task.id != null || task.serial != null) && !task.managed.get())
The text was updated successfully, but these errors were encountered:
guitcastro
pushed a commit
to guitcastro/androidannotations
that referenced
this issue
Feb 4, 2016
BackgroundExecutor assumed that its executor was asynchronous, so that
in execute(Task), a task could not be removed before it has been added
to the TASKS list.
However, this assumption was wrong with a synchronous executor:
directExecute(…) would execute the task synchronously, leading to call
Task#postExecute(), that removes the task from TASKS. Immediately after
the execution, directExecute(…) would add the task to TASKS, which let
the BackgroundExecutor in an incorrect state.
Therefore, add the task to the TASKS list before the execution, so that
it will also work with synchronous executors.
Fixesandroidannotations#1689.
<androidannotations#1689>
First of all, this issue only happens when running robolectric test because I override the Executor, but it can happen in production if tasks are executed too fast.
I have the following executor, that simple execute tasks in serial for test purpose:
And I have the follow test:
The activity testSerial implementation is:
If you run this test, it will cause dead lock. Digging in the code I was able find out why.
Look at this code:
As you see the task is add after the directExecute is called. Let's take a look at the Task clean post executed code:
As you see in this code we remove the task after the execution, but my execution always finish before the Task is added to the stack. Causing a dead lock, because the task is added to to list and never removed.
One possible solution would be simple check if the task is already finished (managed) before add it to the list:
if ( (task.id != null || task.serial != null) && !task.managed.get())
The text was updated successfully, but these errors were encountered: