Files
sourcekit-lsp/Sources/SwiftExtensions/Process+terminate.swift
Alex Hoppen 3bb4690db4 Terminate pending background indexing and preparation tasks when shutting down SourceKit-LSP
When SourceKit-LSP is shut down, we should make sure that we don’t leave behind child processes, which will become orphans after SourceKit-LSP has terminated. What’s worse, when SourceKit-LSP has exited, these processes might not have any process to read their stdout/stderr, which can lead to them running indefinitely.

This change does not cover the termination of subprocess trees. For example, if we launch `swift build` and need to kill it because it doesn’t honor SIGINT, its child processes will still live on. Similarly, if we kill a BSP server, its child processes might live on. Fixing this is a drastically bigger endeavor, likely requiring changes to Foundation and/or TSC. I filed https://github.com/swiftlang/sourcekit-lsp/issues/2080 for it.
2025-03-25 14:10:38 -07:00

39 lines
1.4 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
package import Foundation
extension Foundation.Process {
/// If the process has not exited after `duration`, terminate it.
package func terminateIfRunning(after duration: Duration, pollInterval: Duration = .milliseconds(5)) async throws {
for _ in 0..<Int(duration.seconds / pollInterval.seconds) {
if !self.isRunning {
break
}
try await Task.sleep(for: pollInterval)
}
if self.isRunning {
self.terminate()
}
}
/// On Posix platforms, send a SIGKILL to the process. On Windows, terminate the process.
package func terminateImmediately() {
// TODO: We should also terminate all child processes (https://github.com/swiftlang/sourcekit-lsp/issues/2080)
#if os(Windows)
self.terminate()
#else
Foundation.kill(processIdentifier, SIGKILL) // ignore-unacceptable-language
#endif
}
}