Fix ReactInstanceManager deadlock

Summary:
D12829677 introduced a deadlock where onHostResume holds the lock on `moveToResumedLifecycleState()` then waits for the `mReactContext` lock, but at the same time setupReactContext holds the `mReactContext` lock and waits for `moveToResumedLifecycleState()` https://our.intern.facebook.com/intern/everpaste/?handle=GAgXFgLQH1ZlQikBAMQzo2LZ6h9TbiAxAAAz. The purpose of the previous diff was to make sure that detachRootoView and
setupReactContext did not interfere with each other, and implemented that by blocking on mReactContext. Since this overloads the usage of mReactContext, let's use a different lock `mAttachedRootViews` to implement this behavior instead

Reviewed By: mdvacca

Differential Revision: D12989555

fbshipit-source-id: c12e5fd9c5fa4c2037167e9400dc0c1578e38959
This commit is contained in:
Andrew Chen (Eng)
2018-11-09 13:41:17 -08:00
committed by Facebook Github Bot
parent 80f92adf1f
commit df7e8c64ff
2 changed files with 41 additions and 16 deletions

View File

@@ -741,11 +741,13 @@ public class ReactInstanceManager {
@ThreadConfined(UI)
public void detachRootView(ReactRootView rootView) {
UiThreadUtil.assertOnUiThread();
if (mAttachedRootViews.contains(rootView)) {
ReactContext currentContext = getCurrentReactContext();
mAttachedRootViews.remove(rootView);
if (currentContext != null && currentContext.hasActiveCatalystInstance()) {
detachViewFromInstance(rootView, currentContext.getCatalystInstance());
synchronized (mAttachedRootViews) {
if (mAttachedRootViews.contains(rootView)) {
ReactContext currentContext = getCurrentReactContext();
mAttachedRootViews.remove(rootView);
if (currentContext != null && currentContext.hasActiveCatalystInstance()) {
detachViewFromInstance(rootView, currentContext.getCatalystInstance());
}
}
}
}
@@ -904,10 +906,12 @@ public class ReactInstanceManager {
private void runCreateReactContextOnNewThread(final ReactContextInitParams initParams) {
Log.d(ReactConstants.TAG, "ReactInstanceManager.runCreateReactContextOnNewThread()");
UiThreadUtil.assertOnUiThread();
synchronized (mReactContextLock) {
if (mCurrentReactContext != null) {
tearDownReactContext(mCurrentReactContext);
mCurrentReactContext = null;
synchronized (mAttachedRootViews) {
synchronized (mReactContextLock) {
if (mCurrentReactContext != null) {
tearDownReactContext(mCurrentReactContext);
mCurrentReactContext = null;
}
}
}
@@ -979,8 +983,11 @@ public class ReactInstanceManager {
ReactMarker.logMarker(PRE_SETUP_REACT_CONTEXT_END);
ReactMarker.logMarker(SETUP_REACT_CONTEXT_START);
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "setupReactContext");
synchronized (mReactContextLock) {
mCurrentReactContext = Assertions.assertNotNull(reactContext);
synchronized (mAttachedRootViews) {
synchronized (mReactContextLock) {
mCurrentReactContext = Assertions.assertNotNull(reactContext);
}
CatalystInstance catalystInstance =
Assertions.assertNotNull(reactContext.getCatalystInstance());
@@ -990,10 +997,8 @@ public class ReactInstanceManager {
moveReactContextToCurrentLifecycleState();
ReactMarker.logMarker(ATTACH_MEASURED_ROOT_VIEWS_START);
synchronized (mAttachedRootViews) {
for (ReactRootView rootView : mAttachedRootViews) {
attachRootViewToInstance(rootView);
}
for (ReactRootView rootView : mAttachedRootViews) {
attachRootViewToInstance(rootView);
}
ReactMarker.logMarker(ATTACH_MEASURED_ROOT_VIEWS_END);
}