Skip to content

Commit 4d1fa7a

Browse files
committed
Fix a race condition that could cause the build graph to not be generated when doing initial background indexing
We were making the initial `generateBuildGraph` call in `SourceKitLSPServer` from a `Task`. This means that `generateBuildGraph` could be executed after `waitForUpToDateBuildGraph` was called by `SemanticIndexManager`. Thus `waitForUpToDateBuildGraph` returned immediately and no files were background indexed. Make `generateBuildGraph` immediately schedule a package reload for SwiftPM build systems instead of doing the hop through a `Task`, fixing the race condition. rdar://135551812
1 parent 33e955a commit 4d1fa7a

File tree

9 files changed

+36
-35
lines changed

9 files changed

+36
-35
lines changed

Sources/BuildSystemIntegration/BuildServerBuildSystem.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ extension BuildServerBuildSystem: BuildSystem {
281281
return [ConfiguredTarget(targetID: "dummy", runDestinationID: "dummy")]
282282
}
283283

284-
package func generateBuildGraph() {}
284+
package func scheduleBuildGraphGeneration() {}
285285

286286
package func waitForUpToDateBuildGraph() async {}
287287

Sources/BuildSystemIntegration/BuildSystem.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,10 @@ package protocol BuildSystem: AnyObject, Sendable {
137137
/// Return the list of targets and run destinations that the given document can be built for.
138138
func configuredTargets(for document: DocumentURI) async -> [ConfiguredTarget]
139139

140-
/// Re-generate the build graph.
141-
func generateBuildGraph() async throws
140+
/// Schedule a task that re-generates the build graph. The function may return before the build graph has finished
141+
/// being generated. If clients need to wait for an up-to-date build graph, they should call
142+
/// `waitForUpToDateBuildGraph` afterwards.
143+
func scheduleBuildGraphGeneration() async throws
142144

143145
/// Wait until the build graph has been loaded.
144146
func waitForUpToDateBuildGraph() async

Sources/BuildSystemIntegration/BuildSystemManager.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,8 @@ extension BuildSystemManager {
265265
return settings
266266
}
267267

268-
package func generateBuildGraph() async throws {
269-
try await self.buildSystem?.generateBuildGraph()
268+
package func scheduleBuildGraphGeneration() async throws {
269+
try await self.buildSystem?.scheduleBuildGraphGeneration()
270270
}
271271

272272
package func waitForUpToDateBuildGraph() async {

Sources/BuildSystemIntegration/CompilationDatabaseBuildSystem.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ extension CompilationDatabaseBuildSystem: BuildSystem {
133133
throw PrepareNotSupportedError()
134134
}
135135

136-
package func generateBuildGraph() {}
136+
package func scheduleBuildGraphGeneration() {}
137137

138138
package func waitForUpToDateBuildGraph() async {}
139139

Sources/BuildSystemIntegration/SwiftPMBuildSystem.swift

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -365,10 +365,11 @@ package actor SwiftPMBuildSystem {
365365
extension SwiftPMBuildSystem {
366366
/// (Re-)load the package settings by parsing the manifest and resolving all the targets and
367367
/// dependencies.
368-
package func reloadPackage() async throws {
369-
try await packageLoadingQueue.asyncThrowing {
368+
@discardableResult
369+
package func schedulePackageReload() -> Task<Void, Swift.Error> {
370+
return packageLoadingQueue.asyncThrowing {
370371
try await self.reloadPackageImpl()
371-
}.valuePropagatingCancellation
372+
}
372373
}
373374

374375
/// - Important: Must only be called on `packageLoadingQueue`.
@@ -549,8 +550,8 @@ extension SwiftPMBuildSystem: BuildSystemIntegration.BuildSystem {
549550
return []
550551
}
551552

552-
package func generateBuildGraph() async throws {
553-
try await self.reloadPackage()
553+
package func scheduleBuildGraphGeneration() async throws {
554+
self.schedulePackageReload()
554555
}
555556

556557
package func waitForUpToDateBuildGraph() async {
@@ -743,7 +744,7 @@ extension SwiftPMBuildSystem: BuildSystemIntegration.BuildSystem {
743744
if events.contains(where: { self.fileEventShouldTriggerPackageReload(event: $0) }) {
744745
logger.log("Reloading package because of file change")
745746
await orLog("Reloading package") {
746-
try await self.reloadPackage()
747+
try await self.schedulePackageReload().value
747748
}
748749
}
749750

Sources/SourceKitLSP/SourceKitLSPServer.swift

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -967,13 +967,11 @@ extension SourceKitLSPServer {
967967
guard await condition(buildSystem) else {
968968
return nil
969969
}
970-
Task {
971-
await orLog("Initial build graph generation") {
972-
// Schedule an initial generation of the build graph. Once the build graph is loaded, the build system will send
973-
// call `fileHandlingCapabilityChanged`, which allows us to move documents to a workspace with this build
974-
// system.
975-
try await buildSystem?.generateBuildGraph()
976-
}
970+
await orLog("Initial build graph generation") {
971+
// Schedule an initial generation of the build graph. Once the build graph is loaded, the build system will send
972+
// call `fileHandlingCapabilityChanged`, which allows us to move documents to a workspace with this build
973+
// system.
974+
try await buildSystem?.scheduleBuildGraphGeneration()
977975
}
978976

979977
let projectRoot = await buildSystem?.projectRoot.pathString

Tests/BuildSystemIntegrationTests/BuildSystemManagerTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ class ManualBuildSystem: BuildSystem {
482482
throw PrepareNotSupportedError()
483483
}
484484

485-
package func generateBuildGraph() {}
485+
package func scheduleBuildGraphGeneration() {}
486486

487487
package func waitForUpToDateBuildGraph() async {}
488488

Tests/BuildSystemIntegrationTests/SwiftPMBuildSystemTests.swift

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ final class SwiftPMBuildSystemTests: XCTestCase {
8383
options: SourceKitLSPOptions(),
8484
testHooks: SwiftPMTestHooks()
8585
)
86-
await assertThrowsError(try await buildSystem.generateBuildGraph())
86+
await assertThrowsError(try await buildSystem.schedulePackageReload().value)
8787
}
8888
}
8989

@@ -144,7 +144,7 @@ final class SwiftPMBuildSystemTests: XCTestCase {
144144
options: SourceKitLSPOptions(),
145145
testHooks: SwiftPMTestHooks()
146146
)
147-
try await swiftpmBuildSystem.generateBuildGraph()
147+
try await swiftpmBuildSystem.schedulePackageReload().value
148148

149149
let aswift = packageRoot.appending(components: "Sources", "lib", "a.swift")
150150
let hostTriple = await swiftpmBuildSystem.destinationBuildParameters.triple
@@ -209,7 +209,7 @@ final class SwiftPMBuildSystemTests: XCTestCase {
209209
options: SourceKitLSPOptions(),
210210
testHooks: SwiftPMTestHooks()
211211
)
212-
try await swiftpmBuildSystem.generateBuildGraph()
212+
try await swiftpmBuildSystem.schedulePackageReload().value
213213

214214
let aPlusSomething = packageRoot.appending(components: "Sources", "lib", "a+something.swift")
215215
let hostTriple = await swiftpmBuildSystem.destinationBuildParameters.triple
@@ -272,7 +272,7 @@ final class SwiftPMBuildSystemTests: XCTestCase {
272272
options: SourceKitLSPOptions(swiftPM: options),
273273
testHooks: SwiftPMTestHooks()
274274
)
275-
try await swiftpmBuildSystem.generateBuildGraph()
275+
try await swiftpmBuildSystem.schedulePackageReload().value
276276

277277
let aswift = packageRoot.appending(components: "Sources", "lib", "a.swift")
278278
let hostTriple = await swiftpmBuildSystem.destinationBuildParameters.triple
@@ -354,7 +354,7 @@ final class SwiftPMBuildSystemTests: XCTestCase {
354354
options: SourceKitLSPOptions(),
355355
testHooks: SwiftPMTestHooks()
356356
)
357-
try await swiftpmBuildSystem.generateBuildGraph()
357+
try await swiftpmBuildSystem.schedulePackageReload().value
358358

359359
let source = try resolveSymlinks(packageRoot.appending(component: "Package.swift"))
360360
let arguments = try await unwrap(swiftpmBuildSystem.buildSettings(for: source.asURI, language: .swift))
@@ -391,7 +391,7 @@ final class SwiftPMBuildSystemTests: XCTestCase {
391391
options: SourceKitLSPOptions(),
392392
testHooks: SwiftPMTestHooks()
393393
)
394-
try await swiftpmBuildSystem.generateBuildGraph()
394+
try await swiftpmBuildSystem.schedulePackageReload().value
395395

396396
let aswift = packageRoot.appending(components: "Sources", "lib", "a.swift")
397397
let bswift = packageRoot.appending(components: "Sources", "lib", "b.swift")
@@ -440,7 +440,7 @@ final class SwiftPMBuildSystemTests: XCTestCase {
440440
options: SourceKitLSPOptions(),
441441
testHooks: SwiftPMTestHooks()
442442
)
443-
try await swiftpmBuildSystem.generateBuildGraph()
443+
try await swiftpmBuildSystem.schedulePackageReload().value
444444

445445
let aswift = packageRoot.appending(components: "Sources", "libA", "a.swift")
446446
let bswift = packageRoot.appending(components: "Sources", "libB", "b.swift")
@@ -495,7 +495,7 @@ final class SwiftPMBuildSystemTests: XCTestCase {
495495
options: SourceKitLSPOptions(),
496496
testHooks: SwiftPMTestHooks()
497497
)
498-
try await swiftpmBuildSystem.generateBuildGraph()
498+
try await swiftpmBuildSystem.schedulePackageReload().value
499499

500500
let aswift = packageRoot.appending(components: "Sources", "libA", "a.swift")
501501
let bswift = packageRoot.appending(components: "Sources", "libB", "b.swift")
@@ -539,7 +539,7 @@ final class SwiftPMBuildSystemTests: XCTestCase {
539539
options: SourceKitLSPOptions(),
540540
testHooks: SwiftPMTestHooks()
541541
)
542-
try await swiftpmBuildSystem.generateBuildGraph()
542+
try await swiftpmBuildSystem.schedulePackageReload().value
543543

544544
let acxx = packageRoot.appending(components: "Sources", "lib", "a.cpp")
545545
let bcxx = packageRoot.appending(components: "Sources", "lib", "b.cpp")
@@ -620,7 +620,7 @@ final class SwiftPMBuildSystemTests: XCTestCase {
620620
options: SourceKitLSPOptions(),
621621
testHooks: SwiftPMTestHooks()
622622
)
623-
try await swiftpmBuildSystem.generateBuildGraph()
623+
try await swiftpmBuildSystem.schedulePackageReload().value
624624

625625
let aswift = packageRoot.appending(components: "Sources", "lib", "a.swift")
626626
let arguments = try await unwrap(swiftpmBuildSystem.buildSettings(for: aswift.asURI, language: .swift))
@@ -672,7 +672,7 @@ final class SwiftPMBuildSystemTests: XCTestCase {
672672
options: SourceKitLSPOptions(),
673673
testHooks: SwiftPMTestHooks()
674674
)
675-
try await swiftpmBuildSystem.generateBuildGraph()
675+
try await swiftpmBuildSystem.schedulePackageReload().value
676676

677677
let aswift1 = packageRoot.appending(components: "Sources", "lib", "a.swift")
678678
let aswift2 =
@@ -740,7 +740,7 @@ final class SwiftPMBuildSystemTests: XCTestCase {
740740
options: SourceKitLSPOptions(),
741741
testHooks: SwiftPMTestHooks()
742742
)
743-
try await swiftpmBuildSystem.generateBuildGraph()
743+
try await swiftpmBuildSystem.schedulePackageReload().value
744744

745745
for file in [acpp, ah] {
746746
let args = try unwrap(
@@ -780,7 +780,7 @@ final class SwiftPMBuildSystemTests: XCTestCase {
780780
options: SourceKitLSPOptions(),
781781
testHooks: SwiftPMTestHooks()
782782
)
783-
try await swiftpmBuildSystem.generateBuildGraph()
783+
try await swiftpmBuildSystem.schedulePackageReload().value
784784

785785
let aswift = packageRoot.appending(components: "Sources", "lib", "a.swift")
786786
let arguments = try await unwrap(swiftpmBuildSystem.buildSettings(for: aswift.asURI, language: .swift))
@@ -856,7 +856,7 @@ final class SwiftPMBuildSystemTests: XCTestCase {
856856
options: SourceKitLSPOptions(),
857857
testHooks: SwiftPMTestHooks()
858858
)
859-
try await swiftpmBuildSystem.generateBuildGraph()
859+
try await swiftpmBuildSystem.schedulePackageReload().value
860860

861861
let aswift = packageRoot.appending(components: "Plugins", "MyPlugin", "a.swift")
862862
let hostTriple = await swiftpmBuildSystem.destinationBuildParameters.triple

Tests/SourceKitLSPTests/BuildSystemTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ actor TestBuildSystem: BuildSystem {
7373
throw PrepareNotSupportedError()
7474
}
7575

76-
func generateBuildGraph() {}
76+
func scheduleBuildGraphGeneration() {}
7777

7878
package func waitForUpToDateBuildGraph() async {}
7979

0 commit comments

Comments
 (0)