firefox-ios icon indicating copy to clipboard operation
firefox-ios copied to clipboard

Memory leaks due to retain cycle between UI kit instances in SecondaryButton

Open amanjeetsingh150 opened this issue 1 year ago • 0 comments

Steps to reproduce

UI test to check for disabled suggestions. I wrote this with Maestro and dumped memory leaks at the end of the test through leaks cli. Leaks tools surfaced retain cycle from SecondaryRoundedButton which is common for the view controllers. Attaching the report below

  1. Launch app with command: export SIMCTL_CHILD_MallocStackLogging=1 && xcrun simctl launch booted org.mozilla.ios.Fennec to enable malloc logs and get process id from here.
  2. Run the UI test with maestro test ./path/to/test.yaml
  3. Dump leaks with leaks pid.

Test:

appId: org.mozilla.ios.Fennec
---
- tapOn: 
   text: "Skip"
   optional: true
- tapOn:
   text: "Skip"
   optional: true
- tapOn:
   text: "Skip"
   optional: true
- tapOn: "Search or enter address"
- inputText: "Wikipedia"
- assertNotVisible: "Empty list"
- tapOn:
    id: "urlBar-cancel"
- tapOn:
    id: "TabToolbar.menuButton"
- tapOn:
    id: "settingsLarge"
- tapOn:
    id: "Search"
- tapOn:
    text: "1"
    index: 0
- tapOn: "Settings"
- tapOn: "Done"
- tapOn: "Search or enter address"
- inputText: "Wikipedia"
- assertVisible: "Empty list"

There are total of 7 instances of this ROOT CYCLE: <UIKit>.

Example

STACK OF 1 INSTANCE OF 'ROOT CYCLE: <UIKit>':
50  dyld                                  0x1214003a6 start + 1942
49  dyld_sim                              0x114602f21 start_sim + 10
48  org.mozilla.ios.Fennec                0x110849c96 main + 1014  main.swift:25
47  com.apple.UIKitCore                0x7fff250a32b5 UIApplicationMain + 101
46  com.apple.UIKitCore                0x7fff2509e65a -[UIApplication _run] + 928
45  com.apple.GraphicsServices         0x7fff2cba9c8e GSEventRunModal + 139
44  com.apple.CoreFoundation           0x7fff2036b704 CFRunLoopRunSpecific + 562
43  com.apple.CoreFoundation           0x7fff2036c6ca __CFRunLoopRun + 2761
42  com.apple.CoreFoundation           0x7fff20371ed5 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
41  libdispatch.dylib                  0x7fff20122c1b _dispatch_main_queue_callback_4CF + 31
40  libdispatch.dylib                  0x7fff20123043 _dispatch_main_queue_drain + 1050
39  libdispatch.dylib                  0x7fff20115b25 _dispatch_client_callout + 8
38  libdispatch.dylib                  0x7fff201148e4 _dispatch_call_block_and_release + 12
37  org.mozilla.ios.Fennec                0x10ff28ae8 thunk for @escaping @callee_guaranteed @Sendable () -> () + 40  <compiler-generated>:0
36  org.mozilla.ios.Fennec                0x11023c10f closure #1 in LaunchScreenViewController.launchWith(launchType:) + 175  LaunchScreenViewController.swift:70
35  org.mozilla.ios.Fennec                0x1101bf61e protocol witness for LaunchFinishedLoadingDelegate.launchWith(launchType:) in conformance SceneCoordinator + 30  <compiler-generated>:0
34  org.mozilla.ios.Fennec                0x1101bde37 SceneCoordinator.launchWith(launchType:) + 119  SceneCoordinator.swift:91
33  org.mozilla.ios.Fennec                0x1101be3a1 SceneCoordinator.startLaunch(with:) + 1009  SceneCoordinator.swift:107
32  org.mozilla.ios.Fennec                0x1106647ed LaunchCoordinator.start(with:) + 269  LaunchCoordinator.swift:33
31  org.mozilla.ios.Fennec                0x110664b65 LaunchCoordinator.presentIntroOnboarding(with:isFullScreen:) + 645  LaunchCoordinator.swift:52
30  org.mozilla.ios.Fennec                0x1104fa532 IntroViewController.__allocating_init(viewModel:themeManager:notificationCenter:userDefaults:) + 66  IntroViewController.swift:0
29  org.mozilla.ios.Fennec                0x1104faae0 IntroViewController.init(viewModel:themeManager:notificationCenter:userDefaults:) + 1440  IntroViewController.swift:72
28  org.mozilla.ios.Fennec                0x1104fe3c4 IntroViewController.applyTheme() + 2276  IntroViewController.swift:191
27  libswiftCore.dylib                 0x7fff30a465cd Sequence.forEach(_:) + 413
26  org.mozilla.ios.Fennec                0x1104fe458 closure #1 in IntroViewController.applyTheme() + 72  IntroViewController.swift:191
25  org.mozilla.ios.Fennec                0x11037542b OnboardingCardViewController.applyTheme() + 1163  OnboardingCardViewController.swift:404
24  org.mozilla.ios.Fennec                0x1103743d6 OnboardingCardViewController.setupLinkButton() + 1430  OnboardingCardViewController.swift:366
23  org.mozilla.ios.Fennec                0x110a2bc3c LinkButton.configure(viewModel:) + 604
22  com.apple.UIKitCore                0x7fff256555b8 -[UIView(Hierarchy) layoutBelowIfNeeded] + 1227
21  com.apple.UIKitCore                0x7fff25565f7f -[UIView(AdditionalLayoutSupport) _updateConstraintsAtEngineLevelIfNeededWithViewForVariableChangeNotifications:] + 388
20  com.apple.UIKitCore                0x7fff25564e60 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededWithViewForVariableChangeNotifications:] + 154
19  com.apple.UIKitCore                0x7fff25563b3c -[UIView(AdditionalLayoutSupport) _withUnsatisfiableConstraintsLoggingSuspendedIfEngineDelegateExists:] + 104
18  com.apple.UIKitCore                0x7fff2556530c __100-[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededWithViewForVariableChangeNotifications:]_block_invoke + 85
17  com.apple.CoreAutoLayout           0x7fff60dc32a7 -[NSISEngine withBehaviors:performModifications:] + 84
16  com.apple.UIKitCore                0x7fff255649f6 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededCollectingViews:forSecondPass:] + 848
15  com.apple.UIKitCore                0x7fff255649f6 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededCollectingViews:forSecondPass:] + 848
14  com.apple.UIKitCore                0x7fff255649f6 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededCollectingViews:forSecondPass:] + 848
13  com.apple.UIKitCore                0x7fff255649f6 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededCollectingViews:forSecondPass:] + 848
12  com.apple.UIKitCore                0x7fff255649f6 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededCollectingViews:forSecondPass:] + 848
11  com.apple.UIKitCore                0x7fff255649f6 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededCollectingViews:forSecondPass:] + 848
10  com.apple.UIKitCore                0x7fff25564b76 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededCollectingViews:forSecondPass:] + 1232
9   com.apple.UIKitCore                0x7fff255643f5 -[UIView(AdditionalLayoutSupport) _sendUpdateConstraintsIfNecessaryForSecondPass:] + 81
8   com.apple.UIKitCore                0x7fff2492ac52 -[UIButton _needsDoubleUpdateConstraintsPass] + 138
7   com.apple.UIKitCore                0x7fff24c59eee -[UIButtonConfigurationVisualProvider hasMultilineText] + 27
6   com.apple.UIKitCore                0x7fff24c59d9a -[UIButtonConfigurationVisualProvider updateConfigurationIfNecessary] + 229
5   org.mozilla.ios.Fennec                0x110a30928 @objc SecondaryRoundedButton.updateConfiguration() + 24
4   org.mozilla.ios.Fennec                0x110a30634 SecondaryRoundedButton.updateConfiguration() + 148
3   libswiftUIKit.dylib                0x7fff59d65ae7 UIButton.configuration.getter + 71
2   libswiftCore.dylib                 0x7fff30c9e777 swift_allocObject + 39
1   libswiftCore.dylib                 0x7fff30c9e608 swift_slowAlloc + 40
0   libsystem_malloc.dylib             0x7fff2016ed91 _malloc_zone_malloc + 241 
====
    10 (816 bytes) ROOT CYCLE: <UIKit.ObjCImplWrapper<__C.UIButtonConfiguration> 0x600000641e80> [32]
       9 (784 bytes) __strong impl --> ROOT CYCLE: <UIButtonConfiguration 0x600003a0fa00> [256]
          3 (112 bytes) __strong _titleTextAttributesTransformer --> ROOT CYCLE: <__NSMallocBlock__ 0x60000087ca50> [48]  libswiftUIKit.dylib  thunk for @escaping @callee_guaranteed (@guaranteed [NSAttributedStringKey ..."
             2 (64 bytes) ROOT CYCLE: <Swift closure context 0x600000641e60> [32]
                1 (32 bytes)  + 8 --> ROOT CYCLE: 0x600000641d80 [32]
                   CYCLE BACK TO <UIKit.ObjCImplWrapper<__C.UIButtonConfiguration> 0x600000641e80> [32]
          1 (192 bytes) __strong _background --> <UIBackgroundConfiguration 0x600003314240> [192]
          3 (128 bytes) __strong _resolvedTitle --> <NSConcreteAttributedString 0x600000641e00> [32]
             2 (96 bytes) attributes --> <NSRLEArray 0x600000411c20> [16]
                1 (80 bytes) theList --> <NSMutableRLEArray.theList (struct _NSRefCountedRunArray) 0x6000025395e0> [80]
          1 (96 bytes) __strong _resolvedSymbolConfig --> <UIImageSymbolConfiguration 0x600002217660> [96]

Expected behavior

No leaks

Actual behavior

Observed retain cycles.

Device & build information

  • Device: ? iOS 15.5, iPHone 11
  • Build version: ? Latest main branch
  • First seen version: ?

Notes

Attachments:

  1. Leak report: https://github.com/amanjeetsingh150/firefox-ios/blob/fix-memory-leaks/maestro/leaks/suggestions_leak_report.txt#L628](https://github.com/amanjeetsingh150/firefox-ios/blob/fix-memory-leaks/maestro/leaks/suggestions_leak_report.txt#L440)
  2. Test: https://github.com/amanjeetsingh150/firefox-ios/blob/fix-memory-leaks/maestro/suggestion_visibility.yaml

┆Issue is synchronized with this Jira Task

amanjeetsingh150 avatar Feb 17 '24 09:02 amanjeetsingh150