Skip to content

[ios] Crash in VsyncWaiter when running ios platform view integration test using local engine #182108

Open

Description

@hellohuanlin

Steps to reproduce

  1. Build local engine targeting iOS device et build -c ios_debug_unopt && et build -c host_debug_unopt_arm64
  2. Use local engine for /Users/huanlin/Desktop/flutter/flutter/dev/integration_tests/ios_platform_view_tests by running flutter build ios --debug --local-engine ios_debug_unopt --local-engine-host host_debug_unopt_arm64 --local-engine-src-path ~/Desktop/flutter/flutter/engine/src --config-only
  3. Open in Xcode, hit CMD+U to run unit test
  4. Observe the crash
Thread 1 Queue : com.apple.main-thread (serial)
#0	0x00000002409a90cc in __pthread_kill ()
#1	0x00000001f24ce810 in pthread_kill ()
#2	0x00000001a149ff64 in abort ()
#3	0x00000001099937f4 in fml::KillProcess at /Users/huanlin/Desktop/flutter/flutter/engine/src/flutter/fml/logging.cc:199
#4	0x0000000109993750 in fml::LogMessage::~LogMessage at /Users/huanlin/Desktop/flutter/flutter/engine/src/flutter/fml/logging.cc:186
#5	0x0000000109993810 in fml::LogMessage::~LogMessage at /Users/huanlin/Desktop/flutter/flutter/engine/src/flutter/fml/logging.cc:113
#6	0x000000010af2d530 in flutter::VsyncWaiter::FireCallback at /Users/huanlin/Desktop/flutter/flutter/engine/src/flutter/shell/common/vsync_waiter.cc:90
#7	0x00000001098a8ee0 in flutter::VsyncWaiterIOS::VsyncWaiterIOS(flutter::TaskRunners const&)::$_0::operator()(std::__fl::unique_ptr<flutter::FrameTimingsRecorder, std::__fl::default_delete<flutter::FrameTimingsRecorder>>) const at /Users/huanlin/Desktop/flutter/flutter/engine/src/flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm:37
#8	0x00000001098a8e2c in std::__fl::__invoke[abi:nn210000]<flutter::VsyncWaiterIOS::VsyncWaiterIOS(flutter::TaskRunners const&)::$_0&, std::__fl::unique_ptr<flutter::FrameTimingsRecorder, std::__fl::default_delete<flutter::FrameTimingsRecorder>>> at /Users/huanlin/Desktop/flutter/flutter/engine/src/flutter/third_party/libcxx/include/__type_traits/invoke.h:179
#9	0x00000001098a8de8 in std::__fl::__invoke_void_return_wrapper<void, true>::__call[abi:nn210000]<flutter::VsyncWaiterIOS::VsyncWaiterIOS(flutter::TaskRunners const&)::$_0&, std::__fl::unique_ptr<flutter::FrameTimingsRecorder, std::__fl::default_delete<flutter::FrameTimingsRecorder>>> at /Users/huanlin/Desktop/flutter/flutter/engine/src/flutter/third_party/libcxx/include/__type_traits/invoke.h:251
#10	0x00000001098a8dbc in std::__fl::__invoke_r[abi:nn210000]<void, flutter::VsyncWaiterIOS::VsyncWaiterIOS(flutter::TaskRunners const&)::$_0&, std::__fl::unique_ptr<flutter::FrameTimingsRecorder, std::__fl::default_delete<flutter::FrameTimingsRecorder>>> at /Users/huanlin/Desktop/flutter/flutter/engine/src/flutter/third_party/libcxx/include/__type_traits/invoke.h:273
#11	0x00000001098a8d90 in std::__fl::__function::__alloc_func<flutter::VsyncWaiterIOS::VsyncWaiterIOS(flutter::TaskRunners const&)::$_0, std::__fl::allocator<flutter::VsyncWaiterIOS::VsyncWaiterIOS(flutter::TaskRunners const&)::$_0>, void (std::__fl::unique_ptr<flutter::FrameTimingsRecorder, std::__fl::default_delete<flutter::FrameTimingsRecorder>>)>::operator()[abi:nn210000] at /Users/huanlin/Desktop/flutter/flutter/engine/src/flutter/third_party/libcxx/include/__functional/function.h:167
#12	0x00000001098a8688 in std::__fl::__function::__func<flutter::VsyncWaiterIOS::VsyncWaiterIOS(flutter::TaskRunners const&)::$_0, std::__fl::allocator<flutter::VsyncWaiterIOS::VsyncWaiterIOS(flutter::TaskRunners const&)::$_0>, void (std::__fl::unique_ptr<flutter::FrameTimingsRecorder, std::__fl::default_delete<flutter::FrameTimingsRecorder>>)>::operator() at /Users/huanlin/Desktop/flutter/flutter/engine/src/flutter/third_party/libcxx/include/__functional/function.h:319
#13	0x00000001098aa108 in std::__fl::__function::__value_func<void (std::__fl::unique_ptr<flutter::FrameTimingsRecorder, std::__fl::default_delete<flutter::FrameTimingsRecorder>>)>::operator()[abi:nn210000] at /Users/huanlin/Desktop/flutter/flutter/engine/src/flutter/third_party/libcxx/include/__functional/function.h:436
#14	0x00000001098a7b84 in std::__fl::function<void (std::__fl::unique_ptr<flutter::FrameTimingsRecorder, std::__fl::default_delete<flutter::FrameTimingsRecorder>>)>::operator() at /Users/huanlin/Desktop/flutter/flutter/engine/src/flutter/third_party/libcxx/include/__functional/function.h:995
#15	0x00000001098a796c in -[VSyncClient onDisplayLink:] at /Users/huanlin/Desktop/flutter/flutter/engine/src/flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm:136
#16	0x0000000196662924 in CA::Display::DisplayLinkItem::dispatch_ ()
#17	0x000000019663ff38 in CA::Display::DisplayLink::dispatch_items ()
#18	0x0000000196653770 in CA::Display::DisplayLink::dispatch_deferred_display_links ()
#19	0x000000019b5b6ee4 in _UIUpdateSequenceRunNext ()
#20	0x000000019b5b6374 in schedulerStepScheduledMainSectionContinue ()
#21	0x0000000284a2d560 in UC::DriverCore::continueProcessing ()
#22	0x0000000195c47f10 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ ()
#23	0x0000000195c47e84 in __CFRunLoopDoSource0 ()
#24	0x0000000195c25acc in __CFRunLoopDoSources0 ()
#25	0x0000000195bfc6d8 in __CFRunLoopRun ()
#26	0x0000000195bfba6c in _CFRunLoopRunSpecificWithOptions ()
#27	0x0000000237830498 in GSEventRunModal ()
#28	0x000000019b5d6df8 in -[UIApplication _run] ()
#29	0x000000019b57fe54 in UIApplicationMain ()
#30	0x0000000102bfc63c in main at /Users/huanlin/Desktop/flutter/flutter/dev/integration_tests/ios_platform_view_tests/ios/Runner/main.m:11
#31	0x0000000192c0ee28 in start ()

Expected results

Should not crash

Actual results

Crash

Code sample

NA

Screenshots or Video

No response

Logs

No response

Flutter Doctor output

huanlin@huanlin-mac ios_platform_view_tests % flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[!] Flutter (Channel [user-branch], 3.40.0-1.0.pre-987, on macOS 15.7.3 24G419 darwin-arm64, locale en)
! Flutter version 3.40.0-1.0.pre-987 on channel [user-branch] at /Users/huanlin/Desktop/flutter/flutter
Currently on an unknown channel. Run flutter channel to switch to an official channel.
If that doesn't fix the issue, reinstall Flutter by following instructions at https://flutter.dev/setup.
! Upstream repository unknown source is not a standard remote.
Set environment variable "FLUTTER_GIT_URL" to unknown source to dismiss this error.
[!] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
✗ Flutter requires Android SDK 36 and the Android BuildTools 28.0.3
To update the Android SDK visit https://flutter.dev/to/macos-android-setup for detailed instructions.
! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses
[✓] Xcode - develop for iOS and macOS (Xcode 26.2)
[✓] Chrome - develop for the web
[✓] Connected device (6 available)
! Error: Browsing on the local area network for Huan’s Work iPhone. Ensure the device is unlocked and attached with a cable or associated with the same local area network as this
Mac.
The device must be opted into Developer Mode to connect wirelessly. (code -27)
! Error: Browsing on the local area network for iPhone 13 Mini. Ensure the device is unlocked and attached with a cable or associated with the same local area network as this Mac.
The device must be opted into Developer Mode to connect wirelessly. (code -27)
! Error: Browsing on the local area network for iPad Pro 11 Inch. Ensure the device is unlocked and attached with a cable or associated with the same local area network as this Mac.
The device must be opted into Developer Mode to connect wirelessly. (code -27)
! Error: Browsing on the local area network for Huan’s iPad. Ensure the device is unlocked and attached with a cable or associated with the same local area network as this Mac.
The device must be opted into Developer Mode to connect wirelessly. (code -27)
[✓] Network resources

! Doctor found issues in 2 categories.
huanlin@huanlin-mac ios_platform_view_tests %

Activity

  1. hellohuanlin commented on Feb 9, 2026

    @hellohuanlin
    ContributorAuthor

    As a workaround, I simply commented out KillProcess.

  2. added
    engineflutter/engine related. See also e: labels.
    P2Important issues not at the top of the work list
    triaged-iosTriaged by iOS platform team
    on Feb 12, 2026
  3. vashworth commented on Feb 12, 2026

    @vashworth
    Contributor

    Crashing on:

    FML_DCHECK(fml::TimePoint::Now() >= frame_start_time);

    FML_DCHECK will crash with local engine but not pre-built engines

  4. hellohuanlin commented on Feb 13, 2026

    @hellohuanlin
    ContributorAuthor

    It also reproduces on latest master (pulled today).

  5. removed their assignment
    on Feb 13, 2026
  6. hellohuanlin commented on Feb 23, 2026

    @hellohuanlin
    ContributorAuthor

    I wonder if any insights from team-engine? thank you

  7. gaaclarke commented on Feb 23, 2026

    @gaaclarke
    Member

    So, this is for scheduling callbacks tied to vsync. I poked around with gemini and it seems to think this could be related to apple's ProMotion displays where CACurrentMediaTime() can return a time slightly earlier than the callback. This is what it proposed as a fix.

    diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm
    index e73ed315a7f..5a72afdedb9 100644
    --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm
    +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm
    @@ -114,7 +114,7 @@ double VsyncWaiterIOS::GetRefreshRate() const {
     }
     
     - (void)onDisplayLink:(CADisplayLink*)link {
    -  CFTimeInterval delay = CACurrentMediaTime() - link.timestamp;
    +  CFTimeInterval delay = fmax(0.0, CACurrentMediaTime() - link.timestamp);
       fml::TimePoint frame_start_time = fml::TimePoint::Now() - fml::TimeDelta::FromSecondsF(delay);
     
       CFTimeInterval duration = link.targetTimestamp - link.timestamp;

    I'm not sure if we want to do that since it may be working against some of the ProMotion display's attempts at reducing latency. This could also explain why it wasn't noticed before if the behavior is tied to a new piece of hardware.

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 listengineflutter/engine related. See also e: labels.platform-iosiOS applications specificallyteam-iosOwned by iOS platform teamtriaged-iosTriaged by iOS platform teamworkaround availableThere is a workaround available to overcome the issue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions