Skip to content

Commit

Permalink
Fix Headless Crash Tried to finish non-existent task with id (#46497)
Browse files Browse the repository at this point in the history
Summary:
Sometimes a headless task tries to finish, but it doesn’t exist, which causes an exception.
No one knows how to reliably reproduce it, as it could be a race condition. However, if you attempt to remove a task that has already been removed, it shouldn’t cause an issue since you're trying to remove something that’s already gone (which is exactly what you want).

Fixes:
 - #46496
 - #33883
 - #27597
 - transistorsoft/react-native-background-fetch#202
 - transistorsoft/react-native-background-fetch#369
 - transistorsoft/react-native-background-geolocation#2096
 - jpush/jpush-react-native#78

## Stacktrace:
```
Fatal Exception: java.lang.AssertionError: Tried to finish non-existent task with id 28.
  at com.facebook.infer.annotation.Assertions.assertCondition(Assertions.java:88)
  at com.facebook.react.jstasks.HeadlessJsTaskContext.finishTask(HeadlessJsTaskContext.java:179)
  at com.facebook.react.jstasks.HeadlessJsTaskContext$3.run(HeadlessJsTaskContext.java:217)
  at android.os.Handler.handleCallback(Handler.java:958)
  at android.os.Handler.dispatchMessage(Handler.java:99)
  at android.os.Looper.loopOnce(Looper.java:257)
  at android.os.Looper.loop(Looper.java:368)
  at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:233)
  at java.lang.Thread.run(Thread.java:1012)
```

## Screenshot

https://github.com/user-attachments/assets/101f0f53-95c9-40ec-a59d-22d6d474b457

## Changelog:

[ANDROID] [FIXED] - Fix Headless Crash `Tried to finish non-existent task with id`

Pull Request resolved: #46497

Test Plan:
I created an example where I attempt to remove a task that doesn’t exist.

Example: https://github.com/RodolfoGS/react-native-fix-non-existent-task

### How to reproduce using the example above:
1. `git clone git@github.com:RodolfoGS/react-native-fix-non-existent-task.git`
2. `cd react-native-fix-non-existent-task`
3. `npm install`
4. `npm run android`
5. Notice the crash

### Steps to create the example from scratch and reproduce the crash:
1. `npx react-native-community/cli@latest init AwesomeProject`
2. `cd AwesomeProject`
3. Add call to finishTask to reproduce the crash (RodolfoGS/react-native-fix-non-existent-task@6fe3c13)
4. `npm run android`
5. Notice the crash

Reviewed By: javache

Differential Revision: D62738059

Pulled By: rshest

fbshipit-source-id: 3232dc76ba8a069279c2b741d62372537a3f9140
  • Loading branch information
RodolfoGS authored and facebook-github-bot committed Sep 16, 2024
1 parent 6dbbbe3 commit b4532ad
Showing 1 changed file with 13 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -169,26 +169,25 @@ public void run() {

/**
* Finish a JS task. Doesn't actually stop the task on the JS side, only removes it from the list
* of active tasks and notifies listeners. A task can only be finished once.
* of active tasks and notifies listeners.
*
* @param taskId the unique id returned by {@link #startTask}.
*/
public synchronized void finishTask(final int taskId) {
Assertions.assertCondition(
mActiveTasks.remove(taskId), "Tried to finish non-existent task with id " + taskId + ".");
Assertions.assertCondition(
mActiveTaskConfigs.remove(taskId) != null,
"Tried to remove non-existent task config with id " + taskId + ".");
boolean removed = mActiveTasks.remove(taskId);
mActiveTaskConfigs.remove(taskId);
removeTimeout(taskId);
UiThreadUtil.runOnUiThread(
new Runnable() {
@Override
public void run() {
for (HeadlessJsTaskEventListener listener : mHeadlessJsTaskEventListeners) {
listener.onHeadlessJsTaskFinish(taskId);
if (removed) {
UiThreadUtil.runOnUiThread(
new Runnable() {
@Override
public void run() {
for (HeadlessJsTaskEventListener listener : mHeadlessJsTaskEventListeners) {
listener.onHeadlessJsTaskFinish(taskId);
}
}
}
});
});
}
}

private void removeTimeout(int taskId) {
Expand Down

0 comments on commit b4532ad

Please sign in to comment.