Skip to content

Using Platform Views simultaneously in multiple engines causes a crash. #153211

Open

Description

@jayden320

Steps to reproduce

Steps to reproduce the crash using the Code sample:

  1. Open the app and click the "Show" button in the top left corner to display a dialog.
  2. Click the "push" button in the dialog to open a new page.
  3. Click the "Back (Delay)" button in the top right corner.
  4. A crash will occur at this point.

Another set of steps to reproduce the crash:

  1. Open the app and click the "Show" button in the top left corner to display a dialog.
  2. Click the "push" button in the dialog to open a new page.
  3. Click the "Back" button in the top left corner to return to the previous page.
  4. Click the "pop" button.
  5. 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

crash_demo.zip

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=0
Logs 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

  1. xhw0525 commented on Aug 12, 2024

    @xhw0525

    I have also encountered the same issue where there are inexplicable crashes when using FlutterEngineGroup and PlatformView simultaneously.
    flutter 3.22.2

  2. jayden320 commented on Aug 12, 2024

    @jayden320
    Author

    Currently, I mainly encounter crashes and freezes in three types of scenarios:

    1. 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=0

    2. The 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)

    3. 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
    PlatformView

  3. added
    in triagePresently being triaged by the triage team
    on Aug 12, 2024
  4. huycozy commented on Aug 12, 2024

    @huycozy
    Member

    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 hybrid project 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)
    [✓] Flutter (Channel stable, 3.24.0, on macOS 14.6 23G80 darwin-x64, locale en-VN)
        • Flutter version 3.24.0 on channel stable at /Users/huynq/Documents/GitHub/flutter
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision 80c2e84975 (7 days ago), 2024-07-30 23:06:49 +0700
        • Engine revision b8800d88be
        • Dart version 3.5.0
        • DevTools version 2.37.2
    
    [✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
        • Android SDK at /Users/huynq/Library/Android/sdk
        • Platform android-34, build-tools 34.0.0
        • ANDROID_HOME = /Users/huynq/Library/Android/sdk
        • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
        • Java version OpenJDK Runtime Environment (build 17.0.10+0-17.0.10b1087.21-11572160)
        • All Android licenses accepted.
    
    [✓] Xcode - develop for iOS and macOS (Xcode 15.4)
        • Xcode at /Applications/Xcode15.4.app/Contents/Developer
        • Build 15F31d
        • CocoaPods version 1.15.2
    
    [✓] Chrome - develop for the web
        • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    
    [✓] Android Studio (version 2023.3)
        • Android Studio at /Applications/Android Studio.app/Contents
        • Flutter plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/9212-flutter
        • Dart plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/6351-dart
        • android-studio-dir = /Applications/Android Studio.app/
        • Java version OpenJDK Runtime Environment (build 17.0.10+0-17.0.10b1087.21-11572160)
    
    [✓] VS Code (version 1.91.1)
        • VS Code at /Applications/Visual Studio Code.app/Contents
        • Flutter extension version 3.94.0
    
    [✓] Connected device (2 available)
        • macOS (desktop) • macos  • darwin-x64     • macOS 14.6 23G80 darwin-x64
        • Chrome (web)    • chrome • web-javascript • Google Chrome 127.0.6533.89
    
    [✓] Network resources
        • All expected network resources are available.
    
    • No issues found!
    [!] Flutter (Channel master, 3.24.0-1.0.pre.545, on macOS 14.6 23G80 darwin-x64, locale en-VN)
        • Flutter version 3.24.0-1.0.pre.545 on channel master at /Users/huynq/Documents/GitHub/flutter_master
        ! Warning: `flutter` on your path resolves to /Users/huynq/Documents/GitHub/flutter/bin/flutter, which is not inside your current
          Flutter SDK checkout at /Users/huynq/Documents/GitHub/flutter_master. Consider adding
          /Users/huynq/Documents/GitHub/flutter_master/bin to the front of your path.
        ! Warning: `dart` on your path resolves to /Users/huynq/Documents/GitHub/flutter/bin/dart, which is not inside your current Flutter
          SDK checkout at /Users/huynq/Documents/GitHub/flutter_master. Consider adding /Users/huynq/Documents/GitHub/flutter_master/bin to
          the front of your path.
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision 18186df4b7 (27 hours ago), 2024-08-10 19:57:30 -0400
        • Engine revision d409dcdc9b
        • Dart version 3.6.0 (build 3.6.0-134.0.dev)
        • DevTools version 2.38.0
        • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update
          checks and upgrades.
    
    [✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
        • Android SDK at /Users/huynq/Library/Android/sdk
        • Platform android-34, build-tools 34.0.0
        • ANDROID_HOME = /Users/huynq/Library/Android/sdk
        • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
        • Java version OpenJDK Runtime Environment (build 17.0.10+0-17.0.10b1087.21-11572160)
        • All Android licenses accepted.
    
    [✓] Xcode - develop for iOS and macOS (Xcode 15.4)
        • Xcode at /Applications/Xcode15.4.app/Contents/Developer
        • Build 15F31d
        • CocoaPods version 1.15.2
    
    [✓] Chrome - develop for the web
        • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    
    [✓] Android Studio (version 2024.1)
        • Android Studio at /Applications/Android Studio Koala.app/Contents
        • Flutter plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/9212-flutter
        • Dart plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/6351-dart
        • Java version OpenJDK Runtime Environment (build 17.0.11+0-17.0.11b1207.24-11852314)
    
    [✓] Android Studio (version 2023.3)
        • Android Studio at /Applications/Android Studio.app/Contents
        • Flutter plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/9212-flutter
        • Dart plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/6351-dart
        • android-studio-dir = /Applications/Android Studio.app/
        • Java version OpenJDK Runtime Environment (build 17.0.10+0-17.0.10b1087.21-11572160)
    
    [✓] VS Code (version 1.92.0)
        • VS Code at /Applications/Visual Studio Code.app/Contents
        • Flutter extension version 3.94.0
    
    [✓] Connected device (2 available)
        • macOS (desktop) • macos  • darwin-x64     • macOS 14.6 23G80 darwin-x64
        • Chrome (web)    • chrome • web-javascript • Google Chrome 127.0.6533.100
    
    [✓] Network resources
        • All expected network resources are available.
    
    ! Doctor found issues in 1 category.
  5. added
    c: crashStack traces logged to the console
    platform-iosiOS applications specifically
    engineflutter/engine related. See also e: labels.
    a: existing-appsIntegration with existing apps via the add-to-app flow
    a: platform-viewsEmbedding Android/iOS views in Flutter apps
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    c: fatal crashCrashes that terminate the process
    team-iosOwned by iOS platform team
    and removed
    in triagePresently being triaged by the triage team
    on Aug 12, 2024
  6. added
    P2Important issues not at the top of the work list
    triaged-iosTriaged by iOS platform team
    on Aug 14, 2024
  7. cbracken commented on Aug 14, 2024

    @cbracken
    Member

    /cc @hellohuanlin @jonahwilliams for platform views / thread merging.

    /cc @gaaclarke as fyi or for any thoughts re: multi-engine

  8. jonahwilliams commented on Aug 14, 2024

    @jonahwilliams
    Contributor

    I don't expect this to work.

  9. gaaclarke commented on Aug 14, 2024

    @gaaclarke
    Member

    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).

  10. jayden320 commented on Aug 18, 2024

    @jayden320
    Author

    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.

  11. jayden320 commented on Aug 21, 2024

    @jayden320
    Author

    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.

    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 (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)
    UIKitCore    __UIApplicationFlushRunLoopCATransactionIfTooLate (in UIKitCore)
    UIKitCore    ___processEventQueue (in UIKitCore)
    UIKitCore    ___eventQueueSourceCallback (in UIKitCore)
    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:42)
    dyld    start (in dyld)
    
  12. teemo2025 commented on May 8, 2025

    @teemo2025
  13. XuweiQT commented on May 28, 2025

    @XuweiQT

    I also meet deadlock SIGKILL, latch.Signal() may not have been called.

    try fix as:

    - latch.Wait();
    + latch.WaitWithTimeout(fml::TimeDelta::FromMilliseconds(500));
    
  14. jiechic commented on Aug 13, 2026

    @jiechic
    Image i have the same problem on flutter 3.41.9 with android,not ios
    - flutter activity A(enginegroup-engineA)
    - flutter activity B with platform view(enginegroup-engineB)
    - back to activity A  —— have crash
    
    - flutter activity A(enginegroup-engineA)
    - native activity C 
    - flutter activity B with platform view (enginegroup-engineB)
    - back to activity C and back to activity a —— no crash
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: existing-appsIntegration with existing apps via the add-to-app flowa: platform-viewsEmbedding Android/iOS views in Flutter appsc: crashStack traces logged to the consolec: fatal crashCrashes that terminate the processengineflutter/engine related. See also e: labels.found in release: 3.24Found to occur in 3.24has reproducible stepsThe issue has been confirmed reproducible and is ready to work onplatform-iosiOS applications specificallyteam-iosOwned by iOS platform teamtriaged-iosTriaged by iOS platform team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions