Fix race condition in json decoder (#995)

* Fix race condition in json decoder

* Update CHANGELOG.md
This commit is contained in:
Elliott Williams 2021-01-13 20:42:43 -08:00 committed by GitHub
parent 2277b323f2
commit c194a2e4e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 9 additions and 23 deletions

View File

@ -15,6 +15,7 @@
#### Fixed
- Fixed error message output for `minimumXcodeGenVersion`. [#967](https://github.com/yonaskolb/XcodeGen/pull/967) @joshwalker
- Remove force-unwrapping causing crash for `LegacyTarget`s [#982](https://github.com/yonaskolb/XcodeGen/pull/982) @jcolicchio
- Fixed a race condition in an internal JSON decoder, which would occasionally fail with an error like `Parsing project spec failed: Error Domain=Unspecified error Code=0`. [#995](https://github.com/yonaskolb/XcodeGen/pull/995) @elliottwilliams
#### Internal
- Updated to Yams 4.0.0 [#984](https://github.com/yonaskolb/XcodeGen/pull/984) @swiftty

View File

@ -10,36 +10,21 @@ extension Dictionary where Key: JSONKey {
}
if parallel {
let defaultError = NSError(domain: "Unspecified error", code: 0, userInfo: nil)
var itemResults: [Result<T, Error>] = Array(repeating: .failure(defaultError), count: dictionary.count)
var ops: [BlockOperation] = []
var idx: Int = 0
for (key, _) in dictionary {
ops.append(BlockOperation { [idx] in
let keys = Array(dictionary.keys)
var itemResults: [Result<T, Error>] = Array(repeating: .failure(defaultError), count: keys.count)
itemResults.withUnsafeMutableBufferPointer { buffer in
DispatchQueue.concurrentPerform(iterations: dictionary.count) { idx in
do {
let key = keys[idx]
let jsonDictionary: JSONDictionary = try dictionary.json(atKeyPath: .key(key))
let item = try T(name: key, jsonDictionary: jsonDictionary)
itemResults[idx] = .success(item)
buffer[idx] = .success(item)
} catch {
itemResults[idx] = .failure(error)
buffer[idx] = .failure(error)
}
})
idx += 1
}
let queue = OperationQueue()
queue.qualityOfService = .userInteractive
queue.maxConcurrentOperationCount = 8
queue.addOperations(ops, waitUntilFinished: true)
var items = ContiguousArray<T>()
items.reserveCapacity(itemResults.count)
for result in itemResults {
switch result {
case .failure(let error):
throw error
case .success(let item):
items.append(item)
}
}
return Array(items)
return try itemResults.map { try $0.get() }
} else {
var items: [T] = []
for (key, _) in dictionary {