Title: BackgroundExecutor may cause deadlock for serial tasks · Issue #1689 · androidannotations/androidannotations · GitHub
Open Graph Title: BackgroundExecutor may cause deadlock for serial tasks · Issue #1689 · androidannotations/androidannotations
X Title: BackgroundExecutor may cause deadlock for serial tasks · Issue #1689 · androidannotations/androidannotations
Description: 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 t...
Open Graph Description: 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, t...
X Description: 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, t...
Opengraph URL: https://github.com/androidannotations/androidannotations/issues/1689
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"BackgroundExecutor may cause deadlock for serial tasks","articleBody":"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.\n\nI have the following executor, that simple execute tasks in serial for test purpose:\n\n```\npublic class UIThreadExecutor implements Executor{\n\n @Override\n public void execute(@NonNull Runnable command) {\n try {\n command.run();\n }catch (Exception ignored){\n }\n }\n}\n```\n\nAnd I have the follow test:\n\n```\n\n @Test\n public void testSerial(){\n\n BackgroundExecutor.setExecutor(new UIThreadExecutor());\n\n for (int i = 0; i \u003c 10; i++){\n activity.testSerial();\n }\n await().atMost(10, TimeUnit.SECONDS).until(new Callable\u003cBoolean\u003e() {\n @Override\n public Boolean call() throws Exception {\n return activity.count == 10;\n }\n });\n }\n```\n\nThe activity testSerial implementation is: \n\n```\n public static int count = 0;\n @Background(serial = \"test\")\n public void testSerial(){\n count++;\n System.out.println(\"count = \" + count);\n }\n```\n\nIf you run this test, it will cause dead lock. Digging in the code I was able find out why.\n\nLook at this code:\n\n```\npublic static synchronized void execute(Task task) {\n Future\u003c?\u003e future = null;\n if (task.serial == null || !hasSerialRunning(task.serial)) {\n task.executionAsked = true;\n future = directExecute(task, task.remainingDelay);\n }\n if (task.id != null || task.serial != null) {\n /* keep task */\n task.future = future;\n TASKS.add(task);\n }\n }\n```\n\nAs you see the task is add after the directExecute is called. Let's take a look at the Task clean post executed code:\n\n```\n private void postExecute() {\n if (id == null \u0026\u0026 serial == null) {\n /* nothing to do */\n return;\n }\n CURRENT_SERIAL.set(null);\n synchronized (BackgroundExecutor.class) {\n /* execution complete */\n TASKS.remove(this);\n\n if (serial != null) {\n Task next = take(serial);\n if (next != null) {\n if (next.remainingDelay != 0) {\n /* the delay may not have elapsed yet */\n next.remainingDelay = Math.max(0L, targetTimeMillis - System.currentTimeMillis());\n }\n /* a task having the same serial was queued, execute it */\n BackgroundExecutor.execute(next);\n }\n }\n }\n }\n```\n\nAs 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.\n\nOne 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) \u0026\u0026 !task.managed.get())` \n","author":{"url":"https://github.com/guitcastro","@type":"Person","name":"guitcastro"},"datePublished":"2016-02-04T17:52:49.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},"url":"https://github.com/1689/androidannotations/issues/1689"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:7532e14b-2fed-3ffb-001a-b58ca1657860 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | B58A:E3661:3C3D39:54C2A7:6A62F89B |
| html-safe-nonce | 42dc88a2c122eba071c609bd06cdd966a892a81696d1987353fa00ce75304e6a |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJCNThBOkUzNjYxOjNDM0QzOTo1NEMyQTc6NkE2MkY4OUIiLCJ2aXNpdG9yX2lkIjoiMjQyNzI0Njk3ODk0ODg1NTk2MyIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | c2cf791f2cc3396838370c252e04d05eaad5280362c4af0ebbe191465a1c2384 |
| hovercard-subject-tag | issue:131423840 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/androidannotations/androidannotations/1689/issue_layout |
| twitter:image | https://opengraph.githubassets.com/a354e0054c53af566362be3df33f6719fdc4997a517968e3e6dadeb493f47bb9/androidannotations/androidannotations/issues/1689 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/a354e0054c53af566362be3df33f6719fdc4997a517968e3e6dadeb493f47bb9/androidannotations/androidannotations/issues/1689 |
| og:image:alt | 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, t... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | guitcastro |
| hostname | github.com |
| expected-hostname | github.com |
| None | 59e40dc698184067b40ef2d941585f66ed42711564a879644f984f1eacea129c |
| turbo-cache-control | no-preview |
| go-import | github.com/androidannotations/androidannotations git https://github.com/androidannotations/androidannotations.git |
| octolytics-dimension-user_id | 1315313 |
| octolytics-dimension-user_login | androidannotations |
| octolytics-dimension-repository_id | 3116751 |
| octolytics-dimension-repository_nwo | androidannotations/androidannotations |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 3116751 |
| octolytics-dimension-repository_network_root_nwo | androidannotations/androidannotations |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | b4f544bf80583e749557efd76afda56317b6252d |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width