Repository navigation
Description
Steps to reproduce
Steps to reproduce the crash using the Code sample:
- Open the app and click the "Show" button in the top left corner to display a dialog.
- Click the "push" button in the dialog to open a new page.
- Click the "Back (Delay)" button in the top right corner.
- A crash will occur at this point.
Another set of steps to reproduce the crash:
- Open the app and click the "Show" button in the top left corner to display a dialog.
- Click the "push" button in the dialog to open a new page.
- Click the "Back" button in the top left corner to return to the previous page.
- Click the "pop" button.
- A crash will occur at this point.
My guess is: two engines use platform view at the same time. Removing one of the platform views and triggering a page update will cause the App to crash.
Our iOS app is experiencing a significant number of crashes in production.
We are using an EngineGroup in the native app, so multiple engines may exist simultaneously, and each engine may contain a Platform View.
We have identified that these crashes are caused by the use of Platform Views in the app. If we disable the Platform Views, the crashes disappear.
We are encountering crashes in various scenarios in our production app, such as:
- Using a video player implemented with Platform Views in multiple engines.
- Using charts or WebView implemented with Platform Views in multiple engines.
All of the above scenarios result in crashes.
I saw other similar issues, but I'm not sure if they are the same issue:
#94524
#144623
Expected results
Don't crash
Actual results
App crash
Code sample
Code sample
import UIKit
import Flutter
import FlutterPluginRegistrant
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let flutterEngineGroup = FlutterEngineGroup(name: "abc", project: nil)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow()
let flutterEngine = flutterEngineGroup.makeEngine(with: nil)
GeneratedPluginRegistrant.register(with: flutterEngine);
let vc = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)
vc.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Show", style: .done, target: self, action: #selector(show))
let nc = UINavigationController(rootViewController: vc)
window?.rootViewController = nc
window?.makeKeyAndVisible()
return true
}
@objc func show() {
let flutterEngine = flutterEngineGroup.makeEngine(withEntrypoint: "entryPointB", libraryURI: nil)
GeneratedPluginRegistrant.register(with: flutterEngine);
let vc = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)
vc.view.backgroundColor = UIColor.clear
let methodChannel = FlutterMethodChannel(name: "com.example.flutter/native", binaryMessenger: vc.binaryMessenger)
methodChannel.setMethodCallHandler { [weak vc] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
if call.method == "close" {
vc?.dismiss(animated: false)
}
}
let nc = UINavigationController(rootViewController: vc)
nc.view.backgroundColor = UIColor.clear
nc.modalPresentationStyle = .overFullScreen
nc.navigationBar.isHidden = true
window?.rootViewController?.present(nc, animated: false)
}
}import 'dart:io';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:flutter/services.dart';
void main() => runApp(const MyApp());
void entryPointB() {
runApp(Page2());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(title: 'First'),
);
}
}
class Page2 extends StatelessWidget {
const Page2({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const AppContainer(),
);
}
}
class AppContainer extends StatefulWidget {
const AppContainer({super.key});
@override
State<AppContainer> createState() => _AppContainerState();
}
class _AppContainerState extends State<AppContainer> {
var platform = const MethodChannel('com.example.flutter/native');
@override
void initState() {
super.initState();
Future.delayed(Duration.zero, () {
show();
});
}
show() {
showModalBottomSheet(
context: context,
isDismissible: false,
clipBehavior: Clip.hardEdge,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(12.0)),
),
isScrollControlled: true,
enableDrag: false,
builder: (BuildContext context) {
return SizedBox(
width: 300,
height: 400,
child: Scaffold(
body: SafeArea(
child: Column(
children: [
MaterialButton(
child: const Text('pop'),
onPressed: () async {
Navigator.pop(context);
await Future.delayed(const Duration(seconds: 1));
platform.invokeMethod('close');
},
),
MaterialButton(
child: const Text('push'),
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => const MyHomePage(title: 'Second')));
},
),
],
),
),
),
);
},
);
}
@override
Widget build(BuildContext context) {
return Container(color: Colors.transparent);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
bool _willPop = false;
var controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(const Color(0x00000000))
..setNavigationDelegate(
NavigationDelegate(
onProgress: (int progress) {
// Update loading bar.
},
onPageStarted: (String url) {},
onPageFinished: (String url) {},
onHttpError: (HttpResponseError error) {},
onWebResourceError: (WebResourceError error) {},
onNavigationRequest: (NavigationRequest request) {
if (request.url.startsWith('https://www.youtube.com/')) {
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
),
)
..loadRequest(Uri.parse('https://flutter.dev'));
void _pop() {
if (Platform.isIOS) {
setState(() {
_willPop = true;
});
Future.delayed(const Duration(milliseconds: 350), () {
Navigator.pop(context);
});
} else {
Navigator.pop(context);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: widget.title == 'Second'
? [
MaterialButton(
onPressed: _pop,
child: const Text('Back (Delay)'),
)
]
: null,
),
body: _willPop ? Container() : WebViewWidget(controller: controller),
);
}
}Screenshots or Video
Screenshots / Video demonstration
20240810-114929.mp4
20240810-115002.mp4
Logs
Logs in Code sample
[FATAL:flutter/fml/shared_thread_merger.cc(59)] Check failed: lease_term_ref > 0. lease_term should always be positive when merged, lease_term=0Logs collected by online users - Type 1
Thread 0 name: com.apple.main-thread (cpu_usage: 0.00%)
libsystem_kernel.dylib ___psynch_cvwait (in libsystem_kernel.dylib)
libsystem_pthread.dylib __pthread_cond_wait$VARIANT$mp (in libsystem_pthread.dylib)
Flutter std::_fl::__libcpp_condvar_wait[abi:v15000](_opaque_pthread_cond_t*, _opaque_pthread_mutex_t*) (in
Flutter std::_fl::condition_variable::wait(std::_fl::unique_lock<std::_fl::mutex>&) (in Flutter:condition_variable.cpp:46)
Flutter fml::ManualResetWaitableEvent::Wait() (in
Flutter flutter::PlatformView::NotifyCreated() (in Flutter:platform_view.cc:74)
Flutter -[FlutterViewController viewDidLayoutSubviews] (in Flutter:FlutterViewController.mm:1417)
UIKitCore -[UIView(CALayerDelegate) layoutSublayersOfLayer:] (in UIKitCore)
QuartzCore CA::Layer::layout_if_needed(CA::Transaction*) (in QuartzCore)
QuartzCore CA::Layer::layout_and_display_if_needed(CA::Transaction*) (in QuartzCore)
QuartzCore CA::Context::commit_transaction(CA::Transaction*, double, double*) (in QuartzCore)
QuartzCore CA::Transaction::commit() (in QuartzCore)
QuartzCore CA::Transaction::flush_as_runloop_observer(bool) (in QuartzCore)
CoreFoundation ___CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ (in CoreFoundation)
CoreFoundation ___CFRunLoopDoObservers (in CoreFoundation)
CoreFoundation ___CFRunLoopRun (in CoreFoundation)
CoreFoundation _CFRunLoopRunSpecific (in CoreFoundation)
GraphicsServices _GSEventRunModal (in GraphicsServices)
UIKitCore -[UIApplication _run] (in UIKitCore)
UIKitCore _UIApplicationMain (in UIKitCore)
MyApp main (in MyApp:AppDelegate.swift:40)
dyld ((null))Logs collected by online users - Type 2
Thread 0 name: com.apple.main-thread
libsystem_kernel.dylib ___pthread_kill (in libsystem_kernel.dylib)
libsystem_pthread.dylib _pthread_kill (in libsystem_pthread.dylib)
libsystem_c.dylib _abort (in libsystem_c.dylib)
Flutter fml::KillProcess() (in Flutter:logging.cc:221)
Flutter fml::LogMessage::~LogMessage() (in
Flutter fml::LogMessage::~LogMessage() (in Flutter:logging.cc:133)
Flutter std::_fl::__function::__alloc_func<flutter::Rasterizer::Draw(std::_fl::shared_ptr<flutter::Pipeline<flutter::FrameItem> > const&)::$_0, std::_fl::allocator<flutter::Rasterizer::Draw(std::_fl::shared_ptr<flutter::Pipeline<flutter::FrameItem> > const&)::$_0>, void (std::_fl::unique_ptr<flutter::FrameItem, std::_fl::default_delete<flutter::FrameItem> >)>::operator()[abi:v15000](std::_fl::unique_ptr<flutter::FrameItem, std::_fl::default_delete<flutter::FrameItem> >&&) (in
Flutter std::_fl::__invoke_void_return_wrapper<void, true>::__call<flutter::Rasterizer::Draw(std::_fl::shared_ptr<flutter::Pipeline<flutter::FrameItem> > const&)::$_0&, std::_fl::unique_ptr<flutter::FrameItem, std::_fl::default_delete<flutter::FrameItem> > >(flutter::Rasterizer::Draw(std::_fl::shared_ptr<flutter::Pipeline<flutter::FrameItem> > const&)::$_0&, std::_fl::unique_ptr<flutter::FrameItem, std::_fl::default_delete<flutter::FrameItem> >) (in
Flutter std::_fl::__invoke[abi:v15000]<flutter::Rasterizer::Draw(std::_fl::shared_ptr<std::_fl::__invoke[abi:v15000]::Pipeline<std::_fl::__invoke[abi:v15000]::FrameItem> > const&)::$_0&, std::_fl::unique_ptr<std::_fl::__invoke[abi:v15000]::Pipeline, std::_fl::default_delete<std::_fl::__invoke[abi:v15000]::Pipeline> > >(std::_fl::unique_ptr<std::_fl::__invoke[abi:v15000]::Pipeline, std::_fl::default_delete<std::_fl::__invoke[abi:v15000]::Pipeline> >&&, flutter::Rasterizer::Draw(std::_fl::shared_ptr<std::_fl::__invoke[abi:v15000]::Pipeline<std::_fl::__invoke[abi:v15000]::FrameItem> > const&)::$_0&) (in
Flutter flutter::Rasterizer::Draw(std::_fl::shared_ptr<flutter::Pipeline<flutter::FrameItem> > const&)::$_0::operator()(std::_fl::unique_ptr<flutter::FrameItem, std::_fl::default_delete<flutter::FrameItem> >) const (in
Flutter flutter::Rasterizer::DoDraw(std::_fl::unique_ptr<flutter::FrameTimingsRecorder, std::_fl::default_delete<flutter::FrameTimingsRecorder> >, std::_fl::vector<std::_fl::unique_ptr<flutter::LayerTreeTask, std::_fl::default_delete<flutter::LayerTreeTask> >, std::_fl::allocator<std::_fl::unique_ptr<flutter::LayerTreeTask, std::_fl::default_delete<flutter::LayerTreeTask> > > >) (in
Flutter fml::RasterThreadMerger::DecrementLease() (in
Flutter fml::SharedThreadMerger::DecrementLease(void*) (in
Flutter std::_fl::__function::__func<flutter::Rasterizer::Draw(std::_fl::shared_ptr<flutter::Pipeline<flutter::FrameItem> > const&)::$_0, std::_fl::allocator<flutter::Rasterizer::Draw(std::_fl::shared_ptr<flutter::Pipeline<flutter::FrameItem> > const&)::$_0>, void (std::_fl::unique_ptr<flutter::FrameItem, std::_fl::default_delete<flutter::FrameItem> >)>::operator()(std::_fl::unique_ptr<flutter::FrameItem, std::_fl::default_delete<flutter::FrameItem> >&&) (in Flutter:function.h:359)
Flutter flutter::Pipeline<flutter::FrameItem>::Consume(std::_fl::function<void (std::_fl::unique_ptr<flutter::FrameItem, std::_fl::default_delete<flutter::FrameItem> >)> const&) (in
Flutter std::_fl::function<void (std::_fl::unique_ptr<flutter::FrameItem, std::_fl::default_delete<flutter::FrameItem> >)>::operator()(std::_fl::unique_ptr<flutter::FrameItem, std::_fl::default_delete<flutter::FrameItem> >) const (in
Flutter std::_fl::__function::__value_func<void (std::_fl::unique_ptr<flutter::FrameItem, std::_fl::default_delete<flutter::FrameItem> >)>::operator()[abi:v15000](std::_fl::unique_ptr<flutter::FrameItem, std::_fl::default_delete<flutter::FrameItem> >&&) const (in
Flutter flutter::Rasterizer::Draw(std::_fl::shared_ptr<flutter::Pipeline<flutter::FrameItem> > const&) (in Flutter:rasterizer.cc:255)
Flutter std::_fl::__function::__alloc_func<fml::internal::CopyableLambda<flutter::Shell::OnAnimatorDraw(std::_fl::shared_ptr<flutter::Pipeline<flutter::FrameItem> >)::$_0>, std::_fl::allocator<fml::internal::CopyableLambda<flutter::Shell::OnAnimatorDraw(std::_fl::shared_ptr<flutter::Pipeline<flutter::FrameItem> >)::$_0> >, void ()>::operator()[abi:v15000]() (in
Flutter std::_fl::__invoke_void_return_wrapper<void, true>::__call<fml::internal::CopyableLambda<flutter::Shell::OnAnimatorDraw(std::_fl::shared_ptr<flutter::Pipeline<flutter::FrameItem> >)::$_0>&>(fml::internal::CopyableLambda<flutter::Shell::OnAnimatorDraw(std::_fl::shared_ptr<flutter::Pipeline<flutter::FrameItem> >)::$_0>&) (in
Flutter std::_fl::__invoke[abi:v15000]<fml::internal::CopyableLambda<flutter::Shell::OnAnimatorDraw(std::_fl::shared_ptr<fml::internal::CopyableLambda::Pipeline<fml::internal::CopyableLambda::FrameItem> >)::$_0>&, >(fml::internal::CopyableLambda<flutter::Shell::OnAnimatorDraw(std::_fl::shared_ptr<fml::internal::CopyableLambda::Pipeline<fml::internal::CopyableLambda::FrameItem> >)::$_0>&, fml::internal::CopyableLambda<flutter::Shell::OnAnimatorDraw(std::_fl::shared_ptr<fml::internal::CopyableLambda::Pipeline<fml::internal::CopyableLambda::FrameItem> >)::$_0>&) (in
Flutter fml::internal::CopyableLambda<flutter::Shell::OnAnimatorDraw(std::_fl::shared_ptr<flutter::Pipeline<flutter::FrameItem> >)::$_0>::operator()<>(&&) const (in
Flutter flutter::Shell::OnAnimatorDraw(std::_fl::shared_ptr<flutter::Pipeline<flutter::FrameItem> >)::$_0::operator()() (in
Flutter std::_fl::__function::__func<fml::internal::CopyableLambda<flutter::Shell::OnAnimatorDraw(std::_fl::shared_ptr<flutter::Pipeline<flutter::FrameItem> >)::$_0>, std::_fl::allocator<fml::internal::CopyableLambda<flutter::Shell::OnAnimatorDraw(std::_fl::shared_ptr<flutter::Pipeline<flutter::FrameItem> >)::$_0> >, void ()>::operator()() (in Flutter:function.h:359)
Flutter std::_fl::function<void ()>::operator()() const (in
Flutter std::_fl::__function::__value_func<void ()>::operator()[abi:v15000]() const (in
Flutter fml::MessageLoopImpl::FlushTasks(fml::FlushType) (in Flutter:message_loop_impl.cc:126)
Flutter fml::MessageLoopImpl::RunExpiredTasksNow() (in
Flutter fml::MessageLoopDarwin::OnTimerFire(__CFRunLoopTimer*, fml::MessageLoopDarwin*) (in Flutter:message_loop_darwin.mm:85)
CoreFoundation ___CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ (in CoreFoundation)
CoreFoundation ___CFRunLoopDoTimer (in CoreFoundation)
CoreFoundation ___CFRunLoopDoTimers (in CoreFoundation)
CoreFoundation ___CFRunLoopRun (in CoreFoundation)
CoreFoundation _CFRunLoopRunSpecific (in CoreFoundation)
GraphicsServices _GSEventRunModal (in GraphicsServices)
UIKitCore -[UIApplication _run] (in UIKitCore)
UIKitCore _UIApplicationMain (in UIKitCore)
MyApp main (in MyApp:AppDelegate.swift:40)
dyld start (in dyld)Logs collected by online users - Type 3
Thread 0 name: com.apple.main-thread (cpu_usage: 0.00%)
libsystem_kernel.dylib ___psynch_rw_wrlock (in libsystem_kernel.dylib)
libsystem_pthread.dylib __pthread_rwlock_lock_wait (in libsystem_pthread.dylib)
libsystem_pthread.dylib __pthread_rwlock_lock_slow$VARIANT$mp (in libsystem_pthread.dylib)
Flutter fml::UniqueLock::UniqueLock(fml::SharedMutex&) (in
Flutter fml::UniqueLock::UniqueLock(fml::SharedMutex&) (in
Flutter fml::SyncSwitch::SetSwitch(bool) (in Flutter:sync_switch.cc:36)
Flutter flutter::Shell::SetGpuAvailability(flutter::GpuAvailability) (in Flutter:shell.cc:2264)
Flutter -[FlutterEngine setIsGpuDisabled:] (in Flutter:FlutterEngine.mm:1378)
Flutter -[FlutterEngine flutterDidEnterBackground:] (in Flutter:FlutterEngine.mm:1368)
CoreFoundation ___CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ (in CoreFoundation)
CoreFoundation ____CFXRegistrationPost_block_invoke (in CoreFoundation)
CoreFoundation __CFXRegistrationPost (in CoreFoundation)
CoreFoundation __CFXNotificationPost (in CoreFoundation)
Foundation -[NSNotificationCenter postNotificationName:object:userInfo:] (in Foundation)
UIKitCore ___47-[UIApplication _applicationDidEnterBackground]_block_invoke (in UIKitCore)
UIKitCore +[UIViewController _performWithoutDeferringTransitionsAllowingAnimation:actions:] (in UIKitCore)
UIKitCore -[UIApplication _applicationDidEnterBackground] (in UIKitCore)
UIKitCore ___101-[_UISceneLifecycleMultiplexer _evalTransitionToSettings:fromSettings:forceExit:withTransitionStore:]_block_invoke_2 (in UIKitCore)
UIKitCore __UIScenePerformActionsWithLifecycleActionMask (in UIKitCore)
UIKitCore ___101-[_UISceneLifecycleMultiplexer _evalTransitionToSettings:fromSettings:forceExit:withTransitionStore:]_block_invoke (in UIKitCore)
UIKitCore -[_UISceneLifecycleMultiplexer _performBlock:withApplicationOfDeactivationReasons:fromReasons:] (in UIKitCore)
UIKitCore -[_UISceneLifecycleMultiplexer _evalTransitionToSettings:fromSettings:forceExit:withTransitionStore:] (in UIKitCore)
UIKitCore -[_UISceneLifecycleMultiplexer uiScene:transitionedFromState:withTransitionContext:] (in UIKitCore)
UIKitCore ___186-[_UIWindowSceneFBSSceneTransitionContextDrivenLifecycleSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:]_block_invoke (in UIKitCore)
UIKitCore +[BSAnimationSettings(UIKit) tryAnimatingWithSettings:actions:completion:] (in UIKitCore)
UIKitCore __UISceneSettingsDiffActionPerformChangesWithTransitionContext (in UIKitCore)
UIKitCore -[_UIWindowSceneFBSSceneTransitionContextDrivenLifecycleSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:] (in UIKitCore)
UIKitCore __64-[UIScene scene:didUpdateWithDiff:transitionContext:completion:]_block_invoke.578 (in UIKitCore)
UIKitCore -[UIScene _emitSceneSettingsUpdateResponseForCompletion:afterSceneUpdateWork:] (in UIKitCore)
UIKitCore -[UIScene scene:didUpdateWithDiff:transitionContext:completion:] (in UIKitCore)
UIKitCore -[UIApplicationSceneClientAgent scene:handleEvent:withCompletion:] (in UIKitCore)
FrontBoardServices -[FBSScene updater:didUpdateSettings:withDiff:transitionContext:completion:] (in FrontBoardServices)
FrontBoardServices ___94-[FBSWorkspaceScenesClient _queue_updateScene:withSettings:diff:transitionContext:completion:]_block_invoke_2 (in FrontBoardServices)
FrontBoardServices -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] (in FrontBoardServices)
FrontBoardServices ___94-[FBSWorkspaceScenesClient _queue_updateScene:withSettings:diff:transitionContext:completion:]_block_invoke (in FrontBoardServices)
libdispatch.dylib __dispatch_client_callout (in libdispatch.dylib)
libdispatch.dylib __dispatch_block_invoke_direct$VARIANT$mp (in libdispatch.dylib)
FrontBoardServices ___FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ (in FrontBoardServices)
FrontBoardServices -[FBSSerialQueue _targetQueue_performNextIfPossible] (in FrontBoardServices)
FrontBoardServices -[FBSSerialQueue _performNextFromRunLoopSource] (in FrontBoardServices)
CoreFoundation ___CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ (in CoreFoundation)
CoreFoundation ___CFRunLoopDoSource0 (in CoreFoundation)
CoreFoundation ___CFRunLoopDoSources0 (in CoreFoundation)
CoreFoundation ___CFRunLoopRun (in CoreFoundation)
CoreFoundation _CFRunLoopRunSpecific (in CoreFoundation)
GraphicsServices _GSEventRunModal (in GraphicsServices)
UIKitCore -[UIApplication _run] (in UIKitCore)
UIKitCore _UIApplicationMain (in UIKitCore)
MyApp main (in MyApp:AppDelegate.swift:40)
dyld ((null))Full log (Deleted some business threads):
Log1.txt
Log2.txt
Log3.txt
Flutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.22.2, on macOS 14.5 23F79 darwin-arm64, locale en-CN)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 15.4)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2023.2)
[✓] VS Code (version 1.92.1)
[✓] Connected device (5 available)
Activity
xhw0525 commentedon Aug 12, 2024
I have also encountered the same issue where there are inexplicable crashes when using FlutterEngineGroup and PlatformView simultaneously.
flutter 3.22.2jayden320 commentedon Aug 12, 2024
Currently, I mainly encounter crashes and freezes in three types of scenarios:
Actively remove the platform view in the flutter code
Error Log:
[FATAL:flutter/fml/shared_thread_merger.cc(59)] Check failed: lease_term_ref > 0. lease_term should always be positive when merged, lease_term=0The app retreats to the background
Stack Information:
ml::AutoResetWaitableEvent::Wait() (in Flutter) (waitable_event.cc:75)or
fml::SyncSwitch::SetSwitch(bool) (in Flutter) (sync_switch.cc:36)The app returns to the foreground
Stack Information:
PlatformView::NotifyCreated()The common point is that the app has two or more flutter engines at the same time. And at least two engines contain platform view.

I guess it is related to the thread merging caused by platform view. As shown in the figure
huycozy commentedon Aug 12, 2024
Thanks for your detailed report, @jayden320!
I can reproduce this issue on the latest Flutter stable and master channels on iPhone 15 Pro, iOS 17.5 (emulator).
To be clarified on the steps and sample project: this is an add-to-app scenario. To reproduce it, I ran
hybridproject from XCode and followed the given steps above to see the crash occurs.Based on Flutter traces from Type 1 above, this seems to be similar to #94524. Since this issue has clear steps and reproduction, I will keep this open for other's input.
flutter doctor -v (stable and master)
cbracken commentedon Aug 14, 2024
/cc @hellohuanlin @jonahwilliams for platform views / thread merging.
/cc @gaaclarke as fyi or for any thoughts re: multi-engine
jonahwilliams commentedon Aug 14, 2024
I don't expect this to work.
gaaclarke commentedon Aug 14, 2024
Yea, when you are using a Flutter engine group the threads are shared between engines and when using platform views the threads are manually serialized. I don't think any work has been invested to make this work and it wouldn't be an trivial thing to implement.
The workaround would be to not use Flutter engine groups (or have one Flutter engine group per engine using platform views).
jayden320 commentedon Aug 18, 2024
Thanks for the solution.
I did a test and created a new engine group to open the page. The iOS memory increased by 60MB. This will increase the probability of app OOM. I think using a new engine or engine group is not a good solution.
Is it possible to protect the app from freezing or crashing? It is acceptable that the platform view is unavailable in special scenarios instead of crashing directly.
jayden320 commentedon Aug 21, 2024
In the new version of the app, we created a new engine group for the pages that use the platform view. However, we still received a large number of crash reports.
teemo2025 commentedon May 8, 2025
XuweiQT commentedon May 28, 2025
I also meet
deadlock SIGKILL,latch.Signal()may not have been called.try fix as:
jiechic commentedon Aug 13, 2026
Fix/shared thread merger expired lease (flutter#194200)
Fix/shared thread merger expired lease (flutter#194200)