Skip to content

Commit

Permalink
[CoreFoundation] Ensure that we are thread safe. (dotnet#7391)
Browse files Browse the repository at this point in the history
CFBundleGetAllBundles as per Apple docs is not thread safe, this means
that when we loop over the bundles, and use a property, the value is
updated by a different thread. This means that in some weird cases we
get an IndexOutOfBounds exception. We now store the count and use it in
the loop.

Fixes: xamarin/maccore#940
  • Loading branch information
mandel-macaque authored Nov 8, 2019
1 parent cf6280b commit 452f4dc
Showing 1 changed file with 11 additions and 2 deletions.
13 changes: 11 additions & 2 deletions src/CoreFoundation/CFBundle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,18 @@ public static CFBundle[] GetBundlesFromDirectory (NSUrl directoryUrl, string bun

public static CFBundle[] GetAll ()
{
// as per apple documentation:
// CFBundleGetAllBundles
//
// '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 managedBundles = new CFBundle [cfBundles.Count];
for (int index = 0; index < cfBundles.Count; index++) {
var bundleCount = cfBundles.Count;
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);
}
Expand Down

0 comments on commit 452f4dc

Please sign in to comment.