-
Notifications
You must be signed in to change notification settings - Fork 24.9k
Description
Environment
Environment:
OS: macOS High Sierra 10.13.5
Node: 8.3.0
Yarn: 1.3.2
npm: 6.0.1
Watchman: 4.9.0
Xcode: Xcode 9.3.1 Build version 9E501
Android Studio: 3.1 AI-173.4819257
Packages: (wanted => installed)
react: 16.3.1 => 16.3.1
react-native: 0.55.4 => 0.55.4
Description
During (Android) development I was noticing that sometimes my AsyncTask's were no longer executed. When analyzing the thread dump I noticed that at these times there was always an AsyncTask from React Native's CatalystInstanceImpl alive & running:
https://github.com/facebook/react-native/blob/0.56-stable/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java#L351
"AsyncTask #7@6218" prio=5 tid=0x4f5 nid=NA runnable
java.lang.Thread.State: RUNNABLE
at com.facebook.jni.HybridData$Destructor.deleteNative(HybridData.java:-1)
at com.facebook.jni.HybridData$Destructor.destruct(HybridData.java:73)
at com.facebook.jni.HybridData.resetNative(HybridData.java:39)
- locked <0x1871> (a com.facebook.jni.HybridData)
at com.facebook.react.bridge.CatalystInstanceImpl$1$1.run(CatalystInstanceImpl.java:349)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)Since this task is executed on the global / shared AsyncTask.SERIAL_EXECUTOR other AsyncTask will no longer execute.
It seems like after reloading the bridge this AsyncTask is trying to clean up some (native / c++) resources asynchronously but starts hanging if the bridge is reloaded again while cleaning is still in-progress. I currently related this behavior only to rapid reloading but it might also happen at other moments.
Note that I've only seen it happen when Debugging JS. Without debugging it reloads fine so far.
Reproducible Demo
- Start an Emulator. I used a Nexus 5X / API 27.
react-native init BlockingAsyncTaskcd BlockingAsyncTaskreact-native startopen http://localhost:8081/debugger-uireact-native run-android- In emulator:
CMD+M->Debug JS Remotely adb logcat | grep CatalystInstanceImpl.destroy
Notice that the adb logcat will contain two lines:
06-25 22:21:29.104 30424 30424 D ReactNative: CatalystInstanceImpl.destroy() start
06-25 22:21:29.143 30424 30454 D ReactNative: CatalystInstanceImpl.destroy() end
Which is fine. The start and end logs should be balanced.
- Press R+R again in the emulator:
Again, nicely balanced start and end logs:
06-25 22:27:25.545 30424 30424 D ReactNative: CatalystInstanceImpl.destroy() start
06-25 22:27:25.552 30424 30791 D ReactNative: CatalystInstanceImpl.destroy() end
- But now, try to rapidly reload by pressing R+R+R+R:
This time the log shows:
06-25 22:29:03.440 30424 30424 D ReactNative: CatalystInstanceImpl.destroy() start
06-25 22:29:03.444 30424 30886 D ReactNative: CatalystInstanceImpl.destroy() end
06-25 22:29:03.689 30424 30424 D ReactNative: CatalystInstanceImpl.destroy() start
Notice that the last start log has not been balanced with an end log.
- Any consequent reload now results in only a
startlog but noendlog:
06-25 22:30:01.285 30424 30424 D ReactNative: CatalystInstanceImpl.destroy() start
06-25 22:30:04.127 30424 30424 D ReactNative: CatalystInstanceImpl.destroy() start
06-25 22:30:15.552 30424 30424 D ReactNative: CatalystInstanceImpl.destroy() start
06-25 22:30:20.883 30424 30424 D ReactNative: CatalystInstanceImpl.destroy() start