Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NSArrayM was mutated while being enumerated #1943

Closed
CrixuAMG opened this issue Sep 10, 2019 · 4 comments
Closed

NSArrayM was mutated while being enumerated #1943

CrixuAMG opened this issue Sep 10, 2019 · 4 comments

Comments

@CrixuAMG
Copy link

While testing on iOS I saw the app freeze and display the error below on xcode. I have no experience with the native code part of Capacitor and don't know what to do with it. Is it Capacitor related, OS X Catalina/iOS 13 related? Any information would be great!

2019-09-10 10:58:07.462204+0200 App[4922:1313018] *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x2814fc2a0> was mutated while being enumerated.'
*** First throw call stack:
(0x181521c20 0x18123c0c8 0x181521588 0x18124f0f8 0x104613870 0x10461364c 0x1046c6eb8 0x1046c7228 0x1818ec288 0x181479b20 0x181479b70 0x181478e68 0x181478b00 0x1813f1ab8 0x181478430 0x1817dadcc 0x10413cea8 0x10413d06c 0x10443de48 0x10443f2a8 0x10444d35c 0x18149ce10 0x181497b6c 0x181497088 0x18b5f1534 0x1855b4fb8 0x10413d578 0x181316f30)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

Capacitor 1.2.0
iOS 13.1 beta 2
OS X Mojave 10.14.5

@CrixuAMG
Copy link
Author

Here is a stack trace with more information:

2019-09-12 10:42:04.294673+0200 App[19790:500134] *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x60000170d7d0> was mutated while being enumerated.'
*** First throw call stack:
(
	0   CoreFoundation                      0x00007fff23afdbde __exceptionPreprocess + 350
	1   libobjc.A.dylib                     0x00007fff5015cb20 objc_exception_throw + 48
	2   CoreFoundation                      0x00007fff23afaab0 +[__NSFastEnumerationEnumerator allocWithZone:] + 0
	3   Capacitor                           0x00000001061a4e65 -[CAPPlugin notifyListeners:data:retainUntilConsumed:] + 629
	4   Capacitor                           0x00000001061a4bb8 -[CAPPlugin notifyListeners:data:] + 120
	5   Capacitor                           0x000000010625f6f3 $s9Capacitor26CAPPushNotificationsPluginC026didFailToRegisterForRemoteC9WithError12notificationySo14NSNotificationC_tF + 1043
	6   Capacitor                           0x000000010625f794 $s9Capacitor26CAPPushNotificationsPluginC026didFailToRegisterForRemoteC9WithError12notificationySo14NSNotificationC_tFTo + 68
	7   CoreFoundation                      0x00007fff23a27c1c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
	8   CoreFoundation                      0x00007fff23a270a5 _CFXRegistrationPost1 + 421
	9   CoreFoundation                      0x00007fff23a26e0f ___CFXNotificationPost_block_invoke + 175
	10  CoreFoundation                      0x00007fff23b24fe3 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1811
	11  CoreFoundation                      0x00007fff23a26776 _CFXNotificationPost + 950
	12  Foundation                          0x00007fff255b2429 -[NSNotificationCenter postNotificationName:object:userInfo:] + 59
	13  App                                 0x0000000105e7f4f0 $s3App0A8DelegateC11application_48didFailToRegisterForRemoteNotificationsWithErrorySo13UIApplicationC_s0L0_ptF + 400
	14  App                                 0x0000000105e7f584 $s3App0A8DelegateC11application_48didFailToRegisterForRemoteNotificationsWithErrorySo13UIApplicationC_s0L0_ptFTo + 100
	15  libdispatch.dylib                   0x0000000106eeedf0 _dispatch_call_block_and_release + 12
	16  libdispatch.dylib                   0x0000000106eefd64 _dispatch_client_callout + 8
	17  libdispatch.dylib                   0x0000000106efde1c _dispatch_main_queue_callback_4CF + 1500
	18  CoreFoundation                      0x00007fff23a60699 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
	19  CoreFoundation                      0x00007fff23a5b2f9 __CFRunLoopRun + 2329
	20  CoreFoundation                      0x00007fff23a5a6b6 CFRunLoopRunSpecific + 438
	21  GraphicsServices                    0x00007fff38016bb0 GSEventRunModal + 65
	22  UIKitCore                           0x00007fff46f0990f UIApplicationMain + 1621
	23  App                                 0x0000000105e7f7cb main + 75
	24  libdyld.dylib                       0x00007fff50fe1cf5 start + 1
	25  ???                                 0x0000000000000001 0x0 + 1

@CrixuAMG
Copy link
Author

I think I fixed the bug. While working on the app I noticed a method getting more calls than it should, fixed that and now I cannot reproduce the error anymore. The method that was being called returns the device's information and registers a push notification handler.

@RangerRick
Copy link
Contributor

I have actually run into this issue. Hard to reproduce reliably but it happens when you remove event listeners while there are events being triggered.

I've worked around it in my own code so it won't trigger this time around, but it's a real synchronization problem in Capacitor. The "easy" fix is to iterate by index:

diff --git a/ios/Capacitor/Capacitor/CAPPlugin.m b/ios/Capacitor/Capacitor/CAPPlugin.m
index f0fe9e14..fe153c0a 100644
--- a/ios/Capacitor/Capacitor/CAPPlugin.m
+++ b/ios/Capacitor/Capacitor/CAPPlugin.m
@@ -99,10 +99,14 @@
     }
     return;
   }
-
-  for(CAPPluginCall *call in listenersForEvent) {
-    CAPPluginCallResult *result = [[CAPPluginCallResult alloc] init:data];
-    call.successHandler(result, call);
+
+  for (int i=0; i < listenersForEvent.count; i++) {
+      CAPPluginCall *call = listenersForEvent[i];
+      if (call != nil) {
+        CAPPluginCallResult *result = [[CAPPluginCallResult alloc] init:data];
+        call.successHandler(result, call);
+      }
+    }
   }
 }

...although it could technically drop/miss events because of timing. The "real" fix is to probably use a serial queue of some kind to be sure actions on the event listeners are not all done simultaneously.

@ionitron-bot
Copy link

ionitron-bot bot commented Nov 11, 2022

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Capacitor, please create a new issue and ensure the template is fully filled out.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators Nov 11, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants