Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions change/1756980197-fix-deadlock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Fix deadlock in ReactInstanceWin::DetachRootView by replacing sync call with async",
"packageName": "react-native-windows",
"email": "copilot@github.com",
"dependentChangeType": "patch"
}
16 changes: 16 additions & 0 deletions vnext/Microsoft.ReactNative/QuirkSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ winrt::Microsoft::ReactNative::ReactPropertyId<bool> UseRuntimeSchedulerProperty
return propId;
}

winrt::Microsoft::ReactNative::ReactPropertyId<bool> UseRunOnQueueSyncProperty() noexcept {
winrt::Microsoft::ReactNative::ReactPropertyId<bool> propId{L"ReactNative.QuirkSettings", L"UseRunOnQueueSync"};

return propId;
}

#pragma region IDL interface

/*static*/ void QuirkSettings::SetMatchAndroidAndIOSStretchBehavior(
Expand Down Expand Up @@ -121,6 +127,12 @@ winrt::Microsoft::ReactNative::ReactPropertyId<bool> UseRuntimeSchedulerProperty
ReactPropertyBag(settings.Properties()).Set(UseRuntimeSchedulerProperty(), value);
}

/*static*/ void QuirkSettings::SetUseRunOnQueueSync(
winrt::Microsoft::ReactNative::ReactInstanceSettings settings,
bool value) noexcept {
ReactPropertyBag(settings.Properties()).Set(UseRunOnQueueSyncProperty(), value);
}

#pragma endregion IDL interface

/*static*/ bool QuirkSettings::GetMatchAndroidAndIOSStretchBehavior(ReactPropertyBag properties) noexcept {
Expand Down Expand Up @@ -153,4 +165,8 @@ winrt::Microsoft::ReactNative::ReactPropertyId<bool> UseRuntimeSchedulerProperty
return properties.Get(UseRuntimeSchedulerProperty()).value_or(true);
}

/*static*/ bool QuirkSettings::GetUseRunOnQueueSync(ReactPropertyBag properties) noexcept {
return properties.Get(UseRunOnQueueSyncProperty()).value_or(false);
}

} // namespace winrt::Microsoft::ReactNative::implementation
3 changes: 3 additions & 0 deletions vnext/Microsoft.ReactNative/QuirkSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ struct QuirkSettings : QuirkSettingsT<QuirkSettings> {
winrt::Microsoft::ReactNative::ReactPropertyBag properties) noexcept;
static bool GetSuppressWindowFocusOnViewFocus(winrt::Microsoft::ReactNative::ReactPropertyBag properties) noexcept;
static bool GetUseRuntimeScheduler(winrt::Microsoft::ReactNative::ReactPropertyBag properties) noexcept;
static bool GetUseRunOnQueueSync(winrt::Microsoft::ReactNative::ReactPropertyBag properties) noexcept;

static bool GetEnableFabric(winrt::Microsoft::ReactNative::ReactPropertyBag properties) noexcept;
Comment thread
anupriya13 marked this conversation as resolved.

Expand Down Expand Up @@ -65,6 +66,8 @@ struct QuirkSettings : QuirkSettingsT<QuirkSettings> {
winrt::Microsoft::ReactNative::ReactInstanceSettings settings,
bool value) noexcept;

static void SetUseRunOnQueueSync(winrt::Microsoft::ReactNative::ReactInstanceSettings settings, bool value) noexcept;

#pragma endregion Public API - part of IDL interface
};

Expand Down
5 changes: 5 additions & 0 deletions vnext/Microsoft.ReactNative/QuirkSettings.idl
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ namespace Microsoft.ReactNative
"By default `react-native-windows` will use the new RuntimeScheduler."
"Setting this to false will revert the behavior to previous scheduling logic.")
static void SetUseRuntimeScheduler(ReactInstanceSettings settings, Boolean value);

DOC_STRING(
"By default `react-native-windows` will not call sync JS call: runOnQueueSync."
"Setting this to true will revert the behavior to previous logic and might result in hang.")
static void SetUseRunOnQueueSync(ReactInstanceSettings settings, Boolean value);
}

} // namespace Microsoft.ReactNative
11 changes: 9 additions & 2 deletions vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1514,8 +1514,15 @@ void ReactInstanceWin::DetachRootView(facebook::react::IReactRootView *rootView,
CallJsFunction("AppRegistry", "unmountApplicationComponentAtRootTag", std::move(params));
}

// Give the JS thread time to finish executing
m_jsMessageThread.Load()->runOnQueueSync([]() {});
Comment thread
anupriya13 marked this conversation as resolved.
// QUIRK: Legacy sync behavior can be re-enabled via EnableSyncDetachRootView option
// The sync call was removed to prevent deadlocks with Hermes GC operations
bool useSyncCall = winrt::Microsoft::ReactNative::implementation::QuirkSettings::GetUseRunOnQueueSync(
winrt::Microsoft::ReactNative::ReactPropertyBag(m_reactContext->Properties()));
if (useSyncCall) {
// Legacy behavior: wait for JS thread to finish executing (can cause deadlocks)
m_jsMessageThread.Load()->runOnQueueSync([]() {});
}
// Default behavior: no synchronization call to prevent deadlocks
}

Mso::CntPtr<IReactInstanceInternal> MakeReactInstance(
Expand Down