diff --git a/src/CoreFoundation/CFArray.cs b/src/CoreFoundation/CFArray.cs index 7f5df0e79557..d3b9dd5f08c3 100644 --- a/src/CoreFoundation/CFArray.cs +++ b/src/CoreFoundation/CFArray.cs @@ -35,6 +35,8 @@ using ObjCRuntime; using CFIndex = System.nint; +using CFArrayRef = System.IntPtr; +using CFAllocatorRef = System.IntPtr; namespace CoreFoundation { @@ -149,6 +151,11 @@ public static nint GetCount (IntPtr array) { return CFArrayGetCount (array); } + + [DllImport (Constants.CoreFoundationLibrary)] + extern static CFArrayRef CFArrayCreateCopy (CFAllocatorRef allocator, CFArrayRef theArray); + + public CFArray Clone () => new CFArray (CFArrayCreateCopy (IntPtr.Zero, this.Handle), true); } } diff --git a/src/CoreFoundation/CFBundle.cs b/src/CoreFoundation/CFBundle.cs index 5989890bd407..581e73112a13 100644 --- a/src/CoreFoundation/CFBundle.cs +++ b/src/CoreFoundation/CFBundle.cs @@ -109,14 +109,16 @@ public static CFBundle[] GetAll () // 'This function is potentially expensive and not thread-safe' // // This means, that we should not trust the size of the array, since is a get and - // might be modified by a diff thread. We just use the size returned by the first - // count to avoid a System.IndexOutOfRangeException when looping - using (var cfBundles = new CFArray (CFBundleGetAllBundles ())) { - var bundleCount = cfBundles.Count; + // might be modified by a diff thread. We are going to clone the array and make sure + // that Apple does not modify the array while we work with it. That avoids changes + // in the index or in the bundles returned. + using (var cfBundles = new CFArray (CFBundleGetAllBundles ())) + using (var cfBundlesCopy = cfBundles.Clone () ) { + var bundleCount = cfBundlesCopy.Count; // the property is a C call, calling everytime we loop is not needed var managedBundles = new CFBundle [bundleCount]; for (int index = 0; index < bundleCount; index++) { // follow the get rule, we do not own the object - managedBundles [index] = new CFBundle (cfBundles.GetValue (index), false); + managedBundles [index] = new CFBundle (cfBundlesCopy.GetValue (index), false); } return managedBundles; } diff --git a/tests/xtro-sharpie/common-CoreFoundation.ignore b/tests/xtro-sharpie/common-CoreFoundation.ignore index 3db8cadbd88d..ee1d3a96ee1d 100644 --- a/tests/xtro-sharpie/common-CoreFoundation.ignore +++ b/tests/xtro-sharpie/common-CoreFoundation.ignore @@ -334,7 +334,6 @@ !missing-pinvoke! CFArrayApplyFunction is not bound !missing-pinvoke! CFArrayBSearchValues is not bound !missing-pinvoke! CFArrayContainsValue is not bound -!missing-pinvoke! CFArrayCreateCopy is not bound !missing-pinvoke! CFArrayCreateMutable is not bound !missing-pinvoke! CFArrayCreateMutableCopy is not bound !missing-pinvoke! CFArrayExchangeValuesAtIndices is not bound