mirror of
https://github.com/cirruslabs/tart.git
synced 2026-09-29 18:51:19 +02:00
Fix control socket paths with special characters (#1328)
This commit is contained in:
@@ -45,7 +45,7 @@ struct Exec: AsyncParsableCommand {
|
||||
//
|
||||
// [1]: https://blog.8-p.info/en/2020/06/11/unix-domain-socket-length/
|
||||
if let baseURL = vmDir.controlSocketURL.baseURL {
|
||||
FileManager.default.changeCurrentDirectoryPath(baseURL.path())
|
||||
FileManager.default.changeCurrentDirectoryPath(baseURL.absoluteURL.path(percentEncoded: false))
|
||||
}
|
||||
|
||||
// Switch controlling terminal into raw mode when remote pseudo-terminal is requested
|
||||
|
||||
@@ -73,7 +73,7 @@ struct IP: AsyncParsableCommand {
|
||||
//
|
||||
// [1]: https://blog.8-p.info/en/2020/06/11/unix-domain-socket-length/
|
||||
if let baseURL = controlSocketURL.baseURL {
|
||||
FileManager.default.changeCurrentDirectoryPath(baseURL.path())
|
||||
FileManager.default.changeCurrentDirectoryPath(baseURL.absoluteURL.path(percentEncoded: false))
|
||||
}
|
||||
|
||||
if let ip = try await AgentResolver.ResolveIP(controlSocketURL.relativePath) {
|
||||
|
||||
@@ -22,14 +22,14 @@ class ControlSocket {
|
||||
|
||||
// Remove control socket file from previous "tart run" invocations,
|
||||
// if any, otherwise we may get the "address already in use" error
|
||||
try? FileManager.default.removeItem(atPath: controlSocketURL.path())
|
||||
try? FileManager.default.removeItem(at: controlSocketURL)
|
||||
|
||||
// Change the current working directory to a VM's base directory
|
||||
// to work around Unix domain socket 104 byte limitation [1]
|
||||
//
|
||||
// [1]: https://blog.8-p.info/en/2020/06/11/unix-domain-socket-length/
|
||||
if let baseURL = controlSocketURL.baseURL {
|
||||
FileManager.default.changeCurrentDirectoryPath(baseURL.path())
|
||||
FileManager.default.changeCurrentDirectoryPath(baseURL.absoluteURL.path(percentEncoded: false))
|
||||
}
|
||||
|
||||
do {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import NIO
|
||||
import XCTest
|
||||
@testable import tart
|
||||
|
||||
// Avoid NSObject.bind and Tart's Darwin type shadowing the system function.
|
||||
private let bindTestSocket = bind
|
||||
|
||||
@available(macOS 14, *)
|
||||
final class ControlSocketTests: XCTestCase {
|
||||
func testInitializerCreatesControlSocketBeforeReturning() async throws {
|
||||
@@ -44,6 +48,43 @@ final class ControlSocketTests: XCTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
func testInitializerReplacesStaleSocketInLongEncodedPath() async throws {
|
||||
let temporaryDirectory = try makeTemporaryDirectory()
|
||||
let originalDirectory = FileManager.default.currentDirectoryPath
|
||||
defer {
|
||||
FileManager.default.changeCurrentDirectoryPath(originalDirectory)
|
||||
try? FileManager.default.removeItem(at: temporaryDirectory)
|
||||
}
|
||||
|
||||
let vmDirectory = temporaryDirectory.appendingPathComponent(
|
||||
"Tart Home %# 虚拟机 " + String(repeating: "v", count: 104), isDirectory: true
|
||||
)
|
||||
try FileManager.default.createDirectory(at: vmDirectory, withIntermediateDirectories: false)
|
||||
let socketURL = URL(fileURLWithPath: "control.sock", relativeTo: vmDirectory)
|
||||
XCTAssertGreaterThan(socketURL.path.utf8.count, 104)
|
||||
|
||||
// Closing a POSIX socket leaves its path behind, as exiting "tart run" does.
|
||||
XCTAssertTrue(FileManager.default.changeCurrentDirectoryPath(vmDirectory.path))
|
||||
let expectedDirectory = FileManager.default.currentDirectoryPath
|
||||
let address = try SocketAddress(unixDomainSocketPath: "control.sock")
|
||||
let descriptor = socket(AF_UNIX, SOCK_STREAM, 0)
|
||||
XCTAssertGreaterThanOrEqual(descriptor, 0)
|
||||
XCTAssertEqual(address.withSockAddr { bindTestSocket(descriptor, $0, socklen_t($1)) }, 0)
|
||||
XCTAssertEqual(close(descriptor), 0)
|
||||
XCTAssertTrue(FileManager.default.changeCurrentDirectoryPath(originalDirectory))
|
||||
|
||||
var controlSocket: ControlSocket? = try await ControlSocket(socketURL)
|
||||
let eventLoopGroup = try XCTUnwrap(controlSocket?.eventLoopGroup)
|
||||
do {
|
||||
let serverChannel = try XCTUnwrap(controlSocket?.serverChannel)
|
||||
XCTAssertEqual(FileManager.default.currentDirectoryPath, expectedDirectory)
|
||||
XCTAssertTrue(FileManager.default.fileExists(atPath: socketURL.path))
|
||||
try await serverChannel.executeThenClose { _ in }
|
||||
}
|
||||
controlSocket = nil
|
||||
try await eventLoopGroup.shutdownGracefully()
|
||||
}
|
||||
|
||||
private func makeTemporaryDirectory() throws -> URL {
|
||||
let directory = FileManager.default.temporaryDirectory.appendingPathComponent(
|
||||
UUID().uuidString,
|
||||
|
||||
Reference in New Issue
Block a user