Skip to content

Commit 312e145

Browse files
authored
[Collections] Don't queue populateTargetTrie if there is no data (#3634)
Motivation: `populateTargetTrie`, potentially because it's done in a background queue, causes a lot of random crashes in tests (not just in SwiftPM but other projects as well). The exception happens inside SQLite C library and it's not yet clear what the real cause is. However, since most tests do not use the package collections feature at all, `populateTargetTrie` is basically a no-op and therefore doesn't need to be queued. Modification: Queue `populateTargetTrie` only if there is package collection data. This code change doesn't actually fix anything but may perhaps reduce the chance of crashing. rdar://80840989
1 parent c61078f commit 312e145

File tree

1 file changed

+21
-0
lines changed

1 file changed

+21
-0
lines changed

Sources/PackageCollections/Storage/SQLitePackageCollectionsStorage.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,27 @@ final class SQLitePackageCollectionsStorage: PackageCollectionsStorage, Closable
801801
}
802802

803803
internal func populateTargetTrie(callback: @escaping (Result<Void, Error>) -> Void = { _ in }) {
804+
// Check to see if there is any data before submitting task to queue because otherwise it's no-op anyway
805+
do {
806+
let numberOfCollections: Int = try self.executeStatement("SELECT COUNT(*) FROM \(Self.packageCollectionsTableName);") { statement in
807+
let row = try statement.step()
808+
guard let count = row?.int(at: 0) else {
809+
throw StringError("Failed to get count of \(Self.packageCollectionsTableName) table")
810+
}
811+
return count
812+
}
813+
// No collections means no data, so no need to populate target trie
814+
guard numberOfCollections > 0 else {
815+
self.populateTargetTrieLock.withLock {
816+
self.targetTrieReady = true
817+
}
818+
return callback(.success(()))
819+
}
820+
} catch {
821+
self.diagnosticsEngine?.emit(warning: "Failed to determine if database is empty or not: \(error)")
822+
// Try again in background
823+
}
824+
804825
DispatchQueue.sharedConcurrent.async(group: nil, qos: .background, flags: .assignCurrentContext) {
805826
do {
806827
try self.populateTargetTrieLock.withLock { // Prevent race to populate targetTrie

0 commit comments

Comments
 (0)