Prevent multi-thread modification of the same array with serial array modification...
authorClaudio Cambra <claudio.cambra@nextcloud.com>
Mon, 20 Mar 2023 12:16:24 +0000 (13:16 +0100)
committerClaudio Cambra <claudio.cambra@nextcloud.com>
Fri, 12 May 2023 08:02:37 +0000 (16:02 +0800)
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator.swift

index e7bc514ed0ad37137bfd68c94c19029329033eaf..56e2b6b73a6b6618dc3456d87faf27d6553d44ba 100644 (file)
@@ -259,27 +259,27 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
     private static func metadatasToFileProviderItems(_ itemMetadatas: [NextcloudItemMetadataTable], ncKit: NextcloudKit, completionHandler: @escaping(_ items: [NSFileProviderItem]) -> Void) {
         var items: [NSFileProviderItem] = []
 
+        let conversionQueue = DispatchQueue(label: "metadataToItemConversionQueue", qos: .userInitiated, attributes: .concurrent)
+        let appendQueue = DispatchQueue(label: "enumeratorItemAppendQueue", qos: .userInitiated) // Serial queue
         let dispatchGroup = DispatchGroup()
 
         for itemMetadata in itemMetadatas {
-            dispatchGroup.enter()
-
-            DispatchQueue.global(qos: .userInitiated).async {
+            conversionQueue.async(group: dispatchGroup) {
                 if itemMetadata.e2eEncrypted {
                     Logger.enumeration.info("Skipping encrypted metadata in enumeration: \(itemMetadata.ocId, privacy: .public) \(itemMetadata.fileName, privacy: OSLogPrivacy.auto(mask: .hash))")
-                    dispatchGroup.leave()
                     return
                 }
 
                 if let parentItemIdentifier = NextcloudFilesDatabaseManager.shared.parentItemIdentifierFromMetadata(itemMetadata) {
                     let item = FileProviderItem(metadata: itemMetadata, parentItemIdentifier: parentItemIdentifier, ncKit: ncKit)
                     Logger.enumeration.debug("Will enumerate item with ocId: \(itemMetadata.ocId, privacy: .public) and name: \(itemMetadata.fileName, privacy: OSLogPrivacy.auto(mask: .hash))")
-                    items.append(item)
+
+                    appendQueue.async(group: dispatchGroup) {
+                        items.append(item)
+                    }
                 } else {
                     Logger.enumeration.error("Could not get valid parentItemIdentifier for item with ocId: \(itemMetadata.ocId, privacy: .public) and name: \(itemMetadata.fileName, privacy: OSLogPrivacy.auto(mask: .hash)), skipping enumeration")
                 }
-
-                dispatchGroup.leave()
             }
         }