@@ -19,6 +19,7 @@ import SwiftExtensions
1919
2020import struct TSCBasic. AbsolutePath
2121import class TSCBasic. Process
22+ import struct TSCBasic. ProcessResult
2223
2324private let updateIndexStoreIDForLogging = AtomicUInt32 ( initialValue: 1 )
2425
@@ -120,6 +121,11 @@ public struct UpdateIndexStoreTaskDescription: IndexTaskDescription {
120121 /// See `SemanticIndexManager.logMessageToIndexLog`.
121122 private let logMessageToIndexLog : @Sendable ( _ taskID: IndexTaskID , _ message: String ) -> Void
122123
124+ /// How long to wait until we cancel an update indexstore task. This timeout should be long enough that all
125+ /// `swift-frontend` tasks finish within it. It prevents us from blocking the index if the type checker gets stuck on
126+ /// an expression for a long time.
127+ private let timeout : Duration
128+
123129 /// Test hooks that should be called when the index task finishes.
124130 private let testHooks : IndexTestHooks
125131
@@ -147,6 +153,7 @@ public struct UpdateIndexStoreTaskDescription: IndexTaskDescription {
147153 indexStoreUpToDateTracker: UpToDateTracker < DocumentURI > ,
148154 indexFilesWithUpToDateUnit: Bool ,
149155 logMessageToIndexLog: @escaping @Sendable ( _ taskID: IndexTaskID , _ message: String ) -> Void ,
156+ timeout: Duration ,
150157 testHooks: IndexTestHooks
151158 ) {
152159 self . filesToIndex = filesToIndex
@@ -155,6 +162,7 @@ public struct UpdateIndexStoreTaskDescription: IndexTaskDescription {
155162 self . indexStoreUpToDateTracker = indexStoreUpToDateTracker
156163 self . indexFilesWithUpToDateUnit = indexFilesWithUpToDateUnit
157164 self . logMessageToIndexLog = logMessageToIndexLog
165+ self . timeout = timeout
158166 self . testHooks = testHooks
159167 }
160168
@@ -366,19 +374,21 @@ public struct UpdateIndexStoreTaskDescription: IndexTaskDescription {
366374 let stdoutHandler = PipeAsStringHandler { logMessageToIndexLog ( logID, $0) }
367375 let stderrHandler = PipeAsStringHandler { logMessageToIndexLog ( logID, $0) }
368376
369- // Time out updating of the index store after 2 minutes. We don't expect any single file compilation to take longer
370- // than 2 minutes in practice, so this indicates that the compiler has entered a loop and we probably won't make any
371- // progress here. We will try indexing the file again when it is edited or when the project is re-opened.
372- // 2 minutes have been chosen arbitrarily.
373- let result = try await withTimeout ( . seconds( 120 ) ) {
374- try await Process . run (
375- arguments: processArguments,
376- workingDirectory: workingDirectory,
377- outputRedirection: . stream(
378- stdout: { stdoutHandler. handleDataFromPipe ( Data ( $0) ) } ,
379- stderr: { stderrHandler. handleDataFromPipe ( Data ( $0) ) }
377+ let result : ProcessResult
378+ do {
379+ result = try await withTimeout ( timeout) {
380+ try await Process . run (
381+ arguments: processArguments,
382+ workingDirectory: workingDirectory,
383+ outputRedirection: . stream(
384+ stdout: { stdoutHandler. handleDataFromPipe ( Data ( $0) ) } ,
385+ stderr: { stderrHandler. handleDataFromPipe ( Data ( $0) ) }
386+ )
380387 )
381- )
388+ }
389+ } catch {
390+ logMessageToIndexLog ( logID, " Finished error in \( start. duration ( to: . now) ) : \( error) " )
391+ throw error
382392 }
383393 let exitStatus = result. exitStatus. exhaustivelySwitchable
384394 logMessageToIndexLog ( logID, " Finished with \( exitStatus. description) in \( start. duration ( to: . now) ) " )
0 commit comments