diff --git a/Sources/tart/VMDirectory+OCI.swift b/Sources/tart/VMDirectory+OCI.swift index 69dc766..ed0ec64 100644 --- a/Sources/tart/VMDirectory+OCI.swift +++ b/Sources/tart/VMDirectory+OCI.swift @@ -250,9 +250,18 @@ extension VMDirectory { )) } - let frozenOverlayURL = try Config().tartTmpDir.appendingPathComponent("\(UUID().uuidString).asif") + // Keep the snapshot out of startup GC while this potentially long push + // hashes, uploads, and inspects it. + let frozenOverlayDirectory = try VMDirectory.temporary() + let frozenOverlayLock = try FileLock(lockURL: frozenOverlayDirectory.baseURL) + try frozenOverlayLock.lock() + defer { + try? frozenOverlayLock.unlock() + try? FileManager.default.removeItem(at: frozenOverlayDirectory.baseURL) + } + + let frozenOverlayURL = frozenOverlayDirectory.baseURL.appendingPathComponent("overlay.asif") try FileManager.default.copyItem(at: overlayURL, to: frozenOverlayURL) - defer { try? FileManager.default.removeItem(at: frozenOverlayURL) } let overlaySize = try FileManager.default.attributesOfItem(atPath: frozenOverlayURL.path)[.size] as! Int64 defaultLogger.appendNewLine("pushing overlay...") diff --git a/Tests/TartTests/CommandBehaviorTests.swift b/Tests/TartTests/CommandBehaviorTests.swift index 04acfae..67f9dc7 100644 --- a/Tests/TartTests/CommandBehaviorTests.swift +++ b/Tests/TartTests/CommandBehaviorTests.swift @@ -62,6 +62,25 @@ final class CommandBehaviorTests: XCTestCase { } } + func testGarbageCollectionPreservesLockedTemporaryDirectory() throws { + try withTemporaryTartHome { + let temporaryVMDir = try VMDirectory.temporary() + let lock = try FileLock(lockURL: temporaryVMDir.baseURL) + try lock.lock() + XCTAssertTrue(FileManager.default.createFile( + atPath: temporaryVMDir.overlayURL.path, + contents: Data("overlay".utf8) + )) + + try Config().gc() + XCTAssertTrue(FileManager.default.fileExists(atPath: temporaryVMDir.overlayURL.path)) + + try lock.unlock() + try Config().gc() + XCTAssertFalse(FileManager.default.fileExists(atPath: temporaryVMDir.baseURL.path)) + } + } + private func config() -> VMConfig { VMConfig( platform: Linux(),