Skip to content

flutter#182361 Fix delegate copy on plugins init#182362

Merged
auto-submit[bot] merged 5 commits into
flutter:masterfrom
sncf-connect-tech:fix-delegate
Feb 27, 2026
Merged

flutter#182361 Fix delegate copy on plugins init#182362
auto-submit[bot] merged 5 commits into
flutter:masterfrom
sncf-connect-tech:fix-delegate

Conversation

@eMxPi
Copy link
Copy Markdown
Contributor

@eMxPi eMxPi commented Feb 13, 2026

Fix #182361

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

@eMxPi eMxPi requested a review from a team as a code owner February 13, 2026 10:54
@flutter-dashboard
Copy link
Copy Markdown

This pull request was opened from and to a release candidate branch. This should only be done as part of the official Flutter release process. If you are attempting to make a regular contribution to the Flutter project, please close this PR and follow the instructions at Tree Hygiene for detailed instructions on contributing to Flutter.

Reviewers: Use caution before merging pull requests to release branches. Ensure the proper procedure has been followed.

@github-actions github-actions Bot added platform-ios iOS applications specifically engine flutter/engine related. See also e: labels. team-ios Owned by iOS platform team labels Feb 13, 2026
@eMxPi eMxPi changed the title Fixes #123456 Fix delegate copy on plugins init flutter#182361 Fix delegate copy on plugins init Feb 13, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly fixes a potential crash in application:didFinishLaunchingWithOptions:isFallbackForScene: by iterating over a copy of the _delegates array. This prevents a "mutation during enumeration" error if a delegate modifies the delegate list. The added tests in FlutterPluginAppLifeCycleDelegateTest.mm effectively verify this fix.

However, the same unsafe iteration pattern for (... in _delegates) is used in many other methods within FlutterPluginAppLifeCycleDelegate.mm. These could also lead to crashes under similar circumstances. To make the fix complete and robust, all direct iterations over _delegates should be changed to iterate over [_delegates allObjects].

Some of the methods with this issue include:

  • applicationDidEnterBackground:isFallbackForScene:
  • applicationWillEnterForeground:isFallbackForScene:
  • applicationWillResignActive:isFallbackForScene:
  • applicationDidBecomeActive:isFallbackForScene:
  • handleWillTerminate:
  • application:didRegisterUserNotificationSettings:
  • and several others.

I recommend applying this fix consistently across the entire file to prevent similar crashes in other lifecycle events.

@stuartmorgan-g
Copy link
Copy Markdown
Contributor

FYI @vashworth

We'll need to fix all of these delegate loops, not just the one that crashes in that particular case.

[self.container addDelegate:[[FakePlugin alloc] init]];
} else {
// Case 2: Remove itself during the loop over _delegates
[self.container removeDelegate:self];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC the new convention is to put this kind of logic in didInitializeImplicitFlutterEngine? @vashworth

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, but it's not guaranteed that people have migrated yet.

@vashworth vashworth self-requested a review February 19, 2026 22:14
@eMxPi
Copy link
Copy Markdown
Contributor Author

eMxPi commented Feb 23, 2026

FYI @vashworth

We'll need to fix all of these delegate loops, not just the one that crashes in that particular case.

We pushed a new commit with all the delegate methods

@vashworth
Copy link
Copy Markdown
Contributor

Tests are failing:

FAILED: obj/flutter/shell/platform/darwin/ios/framework/Source/libios_test_flutter.FlutterPluginAppLifeCycleDelegateTest.o 
../../../flutter/buildtools/mac-x64/clang/bin/clang++ -MMD -MF obj/flutter/shell/platform/darwin/ios/framework/Source/libios_test_flutter.FlutterPluginAppLifeCycleDelegateTest.o.d -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D_FORTIFY_SOURCE=2 -D_LIBCPP_DISABLE_AVAILABILITY=1 -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS -D_DEBUG -DSHELL_ENABLE_SOFTWARE -DSHELL_ENABLE_METAL -DSK_TYPEFACE_FACTORY_CORETEXT -DSK_FONTMGR_CORETEXT_AVAILABLE -DSK_CODEC_ENCODES_JPEG -DSK_CODEC_ENCODES_PNG -DSK_CODEC_ENCODES_PNG_WITH_LIBPNG -DSK_CODEC_ENCODES_WEBP -DSK_CODEC_DECODES_JPEG -DSK_CODEC_DECODES_PNG -DSK_CODEC_DECODES_ICO -DSK_CODEC_DECODES_PNG_WITH_LIBPNG -DSK_CODEC_DECODES_WEBP -DSK_HAS_WUFFS_LIBRARY -DSK_CODEC_DECODES_GIF -DSK_XML -DFLUTTER_RUNTIME_MODE_DEBUG=1 -DFLUTTER_RUNTIME_MODE_PROFILE=2 -DFLUTTER_RUNTIME_MODE_RELEASE=3 -DFLUTTER_RUNTIME_MODE_JIT_RELEASE=4 -DDART_LEGACY_API=\[\[deprecated\]\] -DFLUTTER_RUNTIME_MODE=1 -DFLUTTER_JIT_RUNTIME=1 -DSLIMPELLER=1 -DIMPELLER_DEBUG=1 -DIMPELLER_SUPPORTS_RENDERING=1 -DIMPELLER_ENABLE_METAL=1 -DSK_CODEC_DECODES_BMP -DSK_CODEC_DECODES_WBMP -DSK_ENABLE_DUMP_GPU -DSK_FORCE_AAA -DSK_LEGACY_IGNORE_DRAW_VERTICES_BLEND_WITH_NO_SHADER -DSK_DISABLE_LEGACY_METAL_BACKEND_SURFACE -DSK_DISABLE_LEGACY_PARAGRAPH_UNICODE -DSK_SUPPORT_UNSPANNED_APIS -DSK_DISABLE_LEGACY_SHADERCONTEXT -DSK_DISABLE_LOWP_RASTER_PIPELINE -DSK_FORCE_RASTER_PIPELINE_BLITTER -DSK_METAL_WAIT_UNTIL_SCHEDULED -DSK_DISABLE_EFFECT_DESERIALIZATION -DSK_ENABLE_PRECOMPILE -DSK_ASSUME_GL_ES=1 -DU_USING_ICU_NAMESPACE=0 -DU_ENABLE_DYLOAD=0 -DUSE_CHROMIUM_ICU=1 -DU_ENABLE_TRACING=1 -DU_ENABLE_RESOURCE_TRACING=0 -DU_STATIC_IMPLEMENTATION -DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE -DRAPIDJSON_HAS_STDSTRING -DRAPIDJSON_HAS_CXX11_RANGE_FOR -DRAPIDJSON_HAS_CXX11_RVALUE_REFS -DRAPIDJSON_HAS_CXX11_TYPETRAITS -DRAPIDJSON_HAS_CXX11_NOEXCEPT -DSK_ENABLE_PARAGRAPH -DSK_UNICODE_AVAILABLE -DSK_UNICODE_ICU_IMPLEMENTATION -DFLUTTER_API_SYMBOL_PREFIX=Embedder -DFLUTTER_NO_EXPORT -Igen/flutter/shell/platform/darwin/ios -I../../.. -Igen -I../../../flutter/third_party/libcxxabi/include -I../../../flutter/build/secondary/flutter/third_party/libcxx/config -I../../../flutter/prebuilts/Platforms/iPhoneSimulator.platform/Developer/usr/lib -Igen/flutter/shell/platform/darwin/common -I../../../flutter -I../../../flutter/third_party/ocmock/Source -I../../../flutter/third_party/skia -I../../../flutter/txt/src -Igen/flutter -Igen/flutter/impeller/runtime_stage -I../../../flutter/third_party/flatbuffers/include -I../../../flutter/third_party/abseil-cpp -I../../../flutter/third_party/harfbuzz/src -I../../../flutter/third_party/icu/source/common -I../../../flutter/third_party/icu/source/i18n -I../../../flutter/third_party/rapidjson -I../../../flutter/third_party/rapidjson/include -I../../../flutter/third_party -I../../../flutter/third_party/dart/runtime -I../../../flutter/third_party/dart/runtime/include -I../../../flutter/third_party/skia/modules/skparagraph/include -I../../../flutter/third_party/skia/modules/skunicode/include -I../../../flutter/shell/platform/darwin/common/framework/Headers -I../../../flutter/shell/platform/embedder -fvisibility=default -mios-simulator-version-min=13.0 -fno-strict-aliasing --target=x86_64-apple-darwin -arch x86_64 -fcolor-diagnostics -Wall -Wextra -Wendif-labels -Wno-missing-field-initializers -Wno-unused-parameter -Werror -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-psabi -Wno-implicit-int-float-conversion -Wno-deprecated-copy -Wno-deprecated-literal-operator -Wno-unqualified-std-cast-call -Wno-nontrivial-memcall -Wno-non-c-typedef-for-linkage -Wno-range-loop-construct -Wunguarded-availability -Wno-deprecated-declarations -no-canonical-prefixes -Wstring-conversion -Wnewline-eof -O0 -g2 -fvisibility=default -F/Volumes/Work/s/w/ir/cache/builder/engine/src/flutter/prebuilts/Platforms/iPhoneSimulator.platform/Developer/Library/Frameworks -Wunreachable-code -Wno-newline-eof  -Werror=overriding-method-mismatch -Werror=undeclared-selector -fobjc-arc -fvisibility-inlines-hidden -fobjc-call-cxx-cdtors -std=c++20 -Wno-deprecated-this-capture -fno-modules -Xclang -fno-cxx-modules -fno-rtti -nostdinc++ -I../../../flutter/third_party/libcxx/include -I../../../flutter/third_party/libcxxabi/include -nostdinc++ -fvisibility=hidden -fno-exceptions -fdebug-prefix-map=/Volumes/Work/s/w/ir/cache/builder/engine/src/= -Wno-unguarded-availability -Wno-unknown-warning-option -Wno-deprecated-builtins -isysroot ../../../flutter/prebuilts/SDKs/iPhoneSimulator18.2.sdk -mios-simulator-version-min=13.0  -c ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegateTest.mm -o obj/flutter/shell/platform/darwin/ios/framework/Source/libios_test_flutter.FlutterPluginAppLifeCycleDelegateTest.o
../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegateTest.mm:97:21: error: no visible @interface for 'FlutterPluginAppLifeCycleDelegate' declares the selector 'removeDelegate:'
   97 |     [self.container removeDelegate:self];
      |      ~~~~~~~~~~~~~~ ^~~~~~~~~~~~~~
../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegateTest.mm:598:39: error: null passed to a callee that requires a non-null argument [-Werror,-Wnonnull]
  598 |         didFinishLaunchingWithOptions:nil];
      |                                       ^~~
../../../flutter/prebuilts/SDKs/iPhoneSimulator18.2.sdk/usr/include/MacTypes.h:94:19: note: expanded from macro 'nil'
   94 |       #define nil nullptr
      |                   ^~~~~~~
../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegateTest.mm:613:39: error: null passed to a callee that requires a non-null argument [-Werror,-Wnonnull]
  613 |         didFinishLaunchingWithOptions:nil];
      |                                       ^~~
../../../flutter/prebuilts/SDKs/iPhoneSimulator18.2.sdk/usr/include/MacTypes.h:94:19: note: expanded from macro 'nil'
   94 |       #define nil nullptr
      |                   ^~~~~~~
3 errors generated.

@vashworth
Copy link
Copy Markdown
Contributor

@eMxPi This PR is trying to merge into the flutter-3.38-candidate.0 branch. Please change it to target the master branch. Once it lands in master, then we will cherry-pick to beta and stable

@eMxPi eMxPi changed the base branch from flutter-3.38-candidate.0 to master February 23, 2026 20:59
@eMxPi eMxPi requested review from a team and jtmcdole as code owners February 23, 2026 20:59
@reidbaker
Copy link
Copy Markdown
Contributor

I believe you have a bad merge. There are lots of files in this pull request that I do not think you modified.

Copy link
Copy Markdown
Contributor

@reidbaker reidbaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes in the content aware hash (and others) are unrelated to the pr described changes.

@eMxPi eMxPi changed the base branch from master to flutter-3.38-candidate.0 February 24, 2026 07:23
@fluttergithubbot
Copy link
Copy Markdown
Contributor

An existing Git SHA, b470db86f493dbc7e5e46537fe038ae32499d4cb, was detected, and no actions were taken.

To re-trigger presubmits after closing or re-opeing a PR, or pushing a HEAD commit (i.e. with --force) that already was pushed before, push a blank commit (git commit --allow-empty -m "Trigger Build") or rebase to continue.

@eMxPi

This comment was marked as duplicate.

@eMxPi

This comment was marked as duplicate.

@eMxPi
Copy link
Copy Markdown
Contributor Author

eMxPi commented Feb 24, 2026

@eMxPi This PR is trying to merge into the flutter-3.38-candidate.0 branch. Please change it to target the master branch. Once it lands in master, then we will cherry-pick to beta and stable

@vashworth this issue is creating a huge amount of crash for us (and I think for many people who are registering plugins). Do you think we can patch at least the 3.41.x ? Waiting for the next release would be problematic for us

@stuartmorgan-g
Copy link
Copy Markdown
Contributor

stuartmorgan-g commented Feb 24, 2026

@eMxPi Please re-read the comment you are quoting. We do not make fixes directly to stable branches first, and we don't fix old branches while leaving newer branches unfixed. The only way this PR will proceed is if it targets master.

After it lands in master, the cherry pick process can start.

@stuartmorgan-g stuartmorgan-g marked this pull request as draft February 24, 2026 14:19
@eMxPi
Copy link
Copy Markdown
Contributor Author

eMxPi commented Feb 24, 2026

@eMxPi Please re-read the comment you are quoting. We do not make fixes directly to stable branches first, and we don't fix old branches while leaving newer branches unfixed. The only way this PR will proceed is if it targets master.

After it lands in master, the cherry pick process can start.

Yes I saw it, but since the crash is targeting the current release, it'd be faster and better for the community to have this patch instead of waiting for next release (we're currently facing 200k crash each day because of this issue). That's why I'm asking if we can target the 3.41 and i'll rebase accordingly

@stuartmorgan-g
Copy link
Copy Markdown
Contributor

It'd be faster and better for the community to have this patch instead of waiting for next release

Two different people have explained the process by which that can happen. If you are willing to follow that process, we can proceed with this PR, otherwise we can close it and someone else will need to fix the issue.

@eMxPi eMxPi closed this Feb 24, 2026
@github-actions github-actions Bot removed e: impeller Impeller rendering backend issues and features requests team-android Owned by Android platform team team-engine Owned by Engine team d: docs/ flutter/flutter/docs, for contributors platform-macos labels Feb 24, 2026
@stuartmorgan-g
Copy link
Copy Markdown
Contributor

hello, I'm quite new to your process

Being new is fine, but when you are new to a large, well-established project with clearly developed and documented processes, repeatedly asking if you can ignore the process instead of following it is generally not going to be a productive approach.

fixing master to target previous versions seems unlogic to me.

Explaining why this process is industry-standard for large projects would be off-topic for this PR.

@vashworth
Copy link
Copy Markdown
Contributor

Formatting is failing:

[2026-02-24 09:34:27.339826] ERROR: ERROR: Found 1 C++/ObjC/Shader file which was formatted incorrectly.

To fix, run `et format` or:
git apply <<DONE
diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegateTest.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegateTest.mm
index 72c21103333..00000000000 100644
--- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegateTest.mm
+++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegateTest.mm
@@ -607,12 +607,12 @@ FLUTTER_ASSERT_ARC
MutatingDelegate* mutatingDelegate = [[MutatingDelegate alloc] init];
mutatingDelegate.container = delegate;
mutatingDelegate.shouldAdd = YES;  // Add Mode
-
+
[delegate addDelegate:mutatingDelegate];
// Without the fix [_delegates allObjects], this crashes with NSGenericException
BOOL result = [delegate application:[UIApplication sharedApplication]
didFinishLaunchingWithOptions:nil];
-
+
XCTAssertTrue(result);
}
@@ -621,13 +621,13 @@ FLUTTER_ASSERT_ARC
MutatingDelegate* mutatingDelegate = [[MutatingDelegate alloc] init];
mutatingDelegate.container = delegate;
mutatingDelegate.shouldAdd = NO;  // Delete Mode
-
+
[delegate addDelegate:mutatingDelegate];
// Without the fix [_delegates allObjects], this crashes because the _delegates collection is
// modify during the loop
BOOL result = [delegate application:[UIApplication sharedApplication]
didFinishLaunchingWithOptions:nil];
-
+
XCTAssertTrue(result);
}
DONE

@vashworth
Copy link
Copy Markdown
Contributor

Mac mac_unopt is still failing:

FAILED: obj/flutter/shell/platform/darwin/ios/framework/Source/libios_test_flutter.FlutterPluginAppLifeCycleDelegateTest.o 
../../../flutter/buildtools/mac-x64/clang/bin/clang++ -MMD -MF obj/flutter/shell/platform/darwin/ios/framework/Source/libios_test_flutter.FlutterPluginAppLifeCycleDelegateTest.o.d -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D_FORTIFY_SOURCE=2 -D_LIBCPP_DISABLE_AVAILABILITY=1 -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS -D_DEBUG -DSHELL_ENABLE_SOFTWARE -DSHELL_ENABLE_METAL -DSK_TYPEFACE_FACTORY_CORETEXT -DSK_FONTMGR_CORETEXT_AVAILABLE -DSK_CODEC_ENCODES_JPEG -DSK_CODEC_ENCODES_PNG -DSK_CODEC_ENCODES_PNG_WITH_LIBPNG -DSK_CODEC_ENCODES_WEBP -DSK_CODEC_DECODES_JPEG -DSK_CODEC_DECODES_PNG -DSK_CODEC_DECODES_ICO -DSK_CODEC_DECODES_PNG_WITH_LIBPNG -DSK_CODEC_DECODES_WEBP -DSK_HAS_WUFFS_LIBRARY -DSK_CODEC_DECODES_GIF -DSK_XML -DFLUTTER_RUNTIME_MODE_DEBUG=1 -DFLUTTER_RUNTIME_MODE_PROFILE=2 -DFLUTTER_RUNTIME_MODE_RELEASE=3 -DFLUTTER_RUNTIME_MODE_JIT_RELEASE=4 -DDART_LEGACY_API=\[\[deprecated\]\] -DFLUTTER_RUNTIME_MODE=1 -DFLUTTER_JIT_RUNTIME=1 -DSLIMPELLER=1 -DIMPELLER_DEBUG=1 -DIMPELLER_SUPPORTS_RENDERING=1 -DIMPELLER_ENABLE_METAL=1 -DSK_DISABLE_LEGACY_INIT_DECODERS -DSK_ENABLE_DUMP_GPU -DSK_LEGACY_IGNORE_DRAW_VERTICES_BLEND_WITH_NO_SHADER -DSK_DISABLE_LEGACY_PARAGRAPH_UNICODE -DSK_DISABLE_LEGACY_NONCONST_SERIAL_PROCS -DSK_DISABLE_LEGACY_NONCONST_ENCODED_IMAGE_DATA -DSK_DISABLE_LEGACY_SHADERCONTEXT -DSK_DISABLE_LOWP_RASTER_PIPELINE -DSK_FORCE_RASTER_PIPELINE_BLITTER -DSK_METAL_WAIT_UNTIL_SCHEDULED -DSK_DISABLE_EFFECT_DESERIALIZATION -DSK_ENABLE_PRECOMPILE -DSK_ASSUME_GL_ES=1 -DU_USING_ICU_NAMESPACE=0 -DU_ENABLE_DYLOAD=0 -DUSE_CHROMIUM_ICU=1 -DU_ENABLE_TRACING=1 -DU_ENABLE_RESOURCE_TRACING=0 -DU_STATIC_IMPLEMENTATION -DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE -DRAPIDJSON_HAS_STDSTRING -DRAPIDJSON_HAS_CXX11_RANGE_FOR -DRAPIDJSON_HAS_CXX11_RVALUE_REFS -DRAPIDJSON_HAS_CXX11_TYPETRAITS -DRAPIDJSON_HAS_CXX11_NOEXCEPT -DSK_ENABLE_PARAGRAPH -DSK_UNICODE_AVAILABLE -DSK_UNICODE_ICU_IMPLEMENTATION -DFLUTTER_API_SYMBOL_PREFIX=Embedder -DFLUTTER_NO_EXPORT -Igen/flutter/shell/platform/darwin/ios -I../../.. -Igen -I../../../flutter/third_party/libcxxabi/include -I../../../flutter/build/secondary/flutter/third_party/libcxx/config -I../../../flutter/prebuilts/Platforms/iPhoneSimulator.platform/Developer/usr/lib -Igen/flutter/shell/platform/darwin/common -I../../../flutter -I../../../flutter/third_party/ocmock/Source -I../../../flutter/third_party/skia -I../../../flutter/txt/src -Igen/flutter -Igen/flutter/impeller/runtime_stage -I../../../flutter/third_party/flatbuffers/include -I../../../third_party/abseil-cpp -I../../../flutter/third_party/harfbuzz/src -I../../../flutter/third_party/icu/source/common -I../../../flutter/third_party/icu/source/i18n -I../../../flutter/third_party/rapidjson -I../../../flutter/third_party/rapidjson/include -I../../../flutter/third_party -I../../../flutter/third_party/dart/runtime -I../../../flutter/third_party/dart/runtime/include -I../../../flutter/third_party/skia/modules/skparagraph/include -I../../../flutter/third_party/skia/modules/skunicode/include -I../../../flutter/shell/platform/darwin/common/framework/Headers -I../../../flutter/shell/platform/embedder -fvisibility=default -mios-simulator-version-min=13.0 -fno-strict-aliasing --target=x86_64-apple-darwin -arch x86_64 -fcolor-diagnostics -Wall -Wextra -Wendif-labels -Wno-missing-field-initializers -Wno-unused-parameter -Werror -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-psabi -Wno-implicit-int-float-conversion -Wno-deprecated-copy -Wno-deprecated-literal-operator -Wno-unqualified-std-cast-call -Wno-nontrivial-memcall -Wno-non-c-typedef-for-linkage -Wno-range-loop-construct -Wunguarded-availability -Wno-deprecated-declarations -no-canonical-prefixes -Wstring-conversion -Wnewline-eof -O0 -g2 -fvisibility=default -F/Volumes/Work/s/w/ir/cache/builder/engine/src/flutter/prebuilts/Platforms/iPhoneSimulator.platform/Developer/Library/Frameworks -Wunreachable-code -Wno-newline-eof  -Werror=overriding-method-mismatch -Werror=undeclared-selector -fobjc-arc -fvisibility-inlines-hidden -fobjc-call-cxx-cdtors -std=c++20 -Wno-deprecated-this-capture -fno-modules -Xclang -fno-cxx-modules -fno-rtti -nostdinc++ -I../../../flutter/third_party/libcxx/include -I../../../flutter/third_party/libcxxabi/include -nostdinc++ -fvisibility=hidden -fno-exceptions -fdebug-prefix-map=/Volumes/Work/s/w/ir/cache/builder/engine/src/= -Wno-unguarded-availability -isysroot ../../../flutter/prebuilts/SDKs/iPhoneSimulator18.2.sdk -mios-simulator-version-min=13.0  -c ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegateTest.mm -o obj/flutter/shell/platform/darwin/ios/framework/Source/libios_test_flutter.FlutterPluginAppLifeCycleDelegateTest.o
../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegateTest.mm:614:39: error: null passed to a callee that requires a non-null argument [-Werror,-Wnonnull]
  614 |         didFinishLaunchingWithOptions:nil];
      |                                       ^~~
../../../flutter/prebuilts/SDKs/iPhoneSimulator18.2.sdk/usr/include/MacTypes.h:94:19: note: expanded from macro 'nil'
   94 |       #define nil nullptr
      |                   ^~~~~~~
../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegateTest.mm:629:39: error: null passed to a callee that requires a non-null argument [-Werror,-Wnonnull]
  629 |         didFinishLaunchingWithOptions:nil];
      |                                       ^~~
../../../flutter/prebuilts/SDKs/iPhoneSimulator18.2.sdk/usr/include/MacTypes.h:94:19: note: expanded from macro 'nil'
   94 |       #define nil nullptr
      |                   ^~~~~~~
2 errors generated.

@vashworth
Copy link
Copy Markdown
Contributor

@eMxPi This PR is trying to merge into the flutter-3.38-candidate.0 branch. Please change it to target the master branch. Once it lands in master, then we will cherry-pick to beta and stable

@vashworth this issue is creating a huge amount of crash for us (and I think for many people who are registering plugins). Do you think we can patch at least the 3.41.x ? Waiting for the next release would be problematic for us

Yes, I would like to hotfix this to 3.41 ASAP. Please address open comments and failing tests

@eMxPi
Copy link
Copy Markdown
Contributor Author

eMxPi commented Feb 25, 2026

@eMxPi This PR is trying to merge into the flutter-3.38-candidate.0 branch. Please change it to target the master branch. Once it lands in master, then we will cherry-pick to beta and stable

@vashworth this issue is creating a huge amount of crash for us (and I think for many people who are registering plugins). Do you think we can patch at least the 3.41.x ? Waiting for the next release would be problematic for us

Yes, I would like to hotfix this to 3.41 ASAP. Please address open comments and failing tests

hi @vashworth I think I fixed the tests and all the comments, tell me if I'm missing anything!

@hellohuanlin
Copy link
Copy Markdown
Contributor

hi @vashworth I think I fixed the tests and all the comments, tell me if I'm missing anything!

You didn't address either of my 2 comments.

@eMxPi
Copy link
Copy Markdown
Contributor Author

eMxPi commented Feb 26, 2026

hi @vashworth I think I fixed the tests and all the comments, tell me if I'm missing anything!

You didn't address either of my 2 comments.

sorry @hellohuanlin I've just pushed a new commit with your suggestions. Thanks for you review

@auto-submit
Copy link
Copy Markdown
Contributor

auto-submit Bot commented Feb 26, 2026

autosubmit label was removed for flutter/flutter/182362, because This PR has not met approval requirements for merging. Changes were requested by {hellohuanlin, reidbaker}, please make the needed changes and resubmit this PR.
The PR author is not a member of flutter-hackers and needs 2 more review(s) in order to merge this PR.

  • Merge guidelines: A PR needs at least one approved review if the author is already part of flutter-hackers or two member reviews if the author is not a flutter-hacker before re-applying the autosubmit label. Reviewers: If you left a comment approving, please use the "approve" review action instead.

@auto-submit
Copy link
Copy Markdown
Contributor

auto-submit Bot commented Feb 27, 2026

autosubmit label was removed for flutter/flutter/182362, because This PR has not met approval requirements for merging. Changes were requested by {hellohuanlin}, please make the needed changes and resubmit this PR.
The PR author is not a member of flutter-hackers and needs 1 more review(s) in order to merge this PR.

  • Merge guidelines: A PR needs at least one approved review if the author is already part of flutter-hackers or two member reviews if the author is not a flutter-hacker before re-applying the autosubmit label. Reviewers: If you left a comment approving, please use the "approve" review action instead.

@eMxPi
Copy link
Copy Markdown
Contributor Author

eMxPi commented Feb 27, 2026

@eMxPi This PR is trying to merge into the flutter-3.38-candidate.0 branch. Please change it to target the master branch. Once it lands in master, then we will cherry-pick to beta and stable

@vashworth this issue is creating a huge amount of crash for us (and I think for many people who are registering plugins). Do you think we can patch at least the 3.41.x ? Waiting for the next release would be problematic for us

Yes, I would like to hotfix this to 3.41 ASAP. Please address open comments and failing tests

@vashworth or @hellohuanlin could you add the label cp:stable to cherry pick on 3.41 please ?

* delegates during a lifecycle notification loop.
*/
@interface MutatingPlugin : NSObject <FlutterApplicationLifeCycleDelegate>
@property(nonatomic, weak) FlutterPluginAppLifeCycleDelegate* lifecycleDelegate;
Copy link
Copy Markdown
Contributor

@hellohuanlin hellohuanlin Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh Interesting use case, where a plugin (MutatingPlugin) holds a reference to the lifecycleDelegate and registers other plugin (FakePlugin in your example) (rather than FakePlugin registering itself directly).

I am curious what is your actual use case in your app, if you don't mind? @eMxPi

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're using several pubs, but the plugins we're registering "'manually" in the AppDelegate are Batch (batch_flutter) and background_locator_2

Copy link
Copy Markdown
Contributor

@hellohuanlin hellohuanlin Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very interesting use case. thanks for the reference.

Copy link
Copy Markdown
Contributor Author

@eMxPi eMxPi Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very interesting use case. thanks for the reference.

@hellohuanlin no problem. Tell me if you need any more details.

In the meantime, do you think we can apply this to the 3.38.X, we've made a lot of tests with 3.41.3 and are facing several issues linked to accessibility. I'll come back to you with more details

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only hotfix previous stable releases in truly extraordinary circumstances; this would not meet that bar. If you need a fix for 3.38, you would either need to maintain your own fork of the engine, or find a plugin-level workaround (such as doing any additional registration asynchronously).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stuartmorgan-g yes I know, but since the 3.41 has several accessibility issues (i'm waiting for the full report of our tester to give you details about it) I think fixing the regression introduced by the 3.38 would be appreciated by the community.
As you can see in the fix i've produced, it's not in the way plugins are registered but I the modification of the code in 3.38 (no longer using a copy but a direct reference to a changing object). So restoring the right way the engine is (and should) work would be appreciated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think fixing the regression introduced by the 3.38 would be appreciated by the community.

There will always be some people who want specific fixes in arbitrary old versions of Flutter; that doesn't change our policy. If this had been reported earlier, it could have been fixed in 3.38.x via our normal process. Since it wasn't, that's no longer an option.

As you can see in the fix i've produced, it's not in the way plugins are registered but I the modification of the code in 3.38 (no longer using a copy but a direct reference to a changing object).

I understand both the bug and the fix. What I described is not a fix, it's a client-level workaround.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cp: stable cherry pick this pull request to stable release candidate branch engine flutter/engine related. See also e: labels. platform-ios iOS applications specifically team-ios Owned by iOS platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[iOS] Crash NSGenericException in FlutterPluginAppLifeCycleDelegate (mutation while enumeration)

8 participants