containerization: guard patch #3's 'import os' behind #if canImport(os)
The swiftly toolchain used by the vminit-image CI resolves Foundation/ Virtualization but not the 'os' overlay, so 'import os' failed with "no such module 'os'". Guarding the diagnostic logger degrades it to a no-op under such toolchains while local (Xcode) builds keep it. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
+4
-1
@@ -35,7 +35,10 @@ in-tree means the patch can't be lost to a dependency re-resolve.
|
|||||||
readability handler is never wired and the agent's stdin is never delivered (it hangs) or its
|
readability handler is never wired and the agent's stdin is never delivered (it hangs) or its
|
||||||
stdout is never read (the "no output, just a spinner" symptom in Nucleic Control containers).
|
stdout is never read (the "no output, just a spinner" symptom in Nucleic Control containers).
|
||||||
Behavior is unchanged; it only surfaces the failing stream. Marked `[Nucleic vendored patch]`
|
Behavior is unchanged; it only surfaces the failing stream. Marked `[Nucleic vendored patch]`
|
||||||
(the `import os`, the `nucleicIOLog` static, and the per-stream check in `setupIO`).
|
(the `import os`, the `nucleicIOLog` static, and the per-stream check in `setupIO`). All three are
|
||||||
|
wrapped in `#if canImport(os)` — the swiftly toolchain used by `.github/workflows/vminit-image.yml`
|
||||||
|
resolves Foundation/Virtualization but not the `os` overlay, so the diagnostic degrades to a no-op
|
||||||
|
there instead of failing the build; Xcode (local) builds keep it.
|
||||||
|
|
||||||
4. **Trimmed for footprint (no behavior change).** `Tests/`, `docs/`, `examples/`, and `images/`
|
4. **Trimmed for footprint (no behavior change).** `Tests/`, `docs/`, `examples/`, and `images/`
|
||||||
were dropped, and the corresponding `.testTarget(...)` entries removed from `Package.swift`. The
|
were dropped, and the corresponding `.testTarget(...)` entries removed from `Package.swift`. The
|
||||||
|
|||||||
@@ -21,13 +21,22 @@ import ContainerizationOS
|
|||||||
import Foundation
|
import Foundation
|
||||||
import Logging
|
import Logging
|
||||||
import Synchronization
|
import Synchronization
|
||||||
import os // [Nucleic vendored patch] stdio-connection diagnostics
|
|
||||||
|
// [Nucleic vendored patch] stdio-connection diagnostics. Guarded: the `os` overlay isn't importable
|
||||||
|
// under every toolchain that builds this package (e.g. the swiftly Swift used by the vminit-image CI,
|
||||||
|
// which resolves Foundation/Virtualization but not `os`), so the diagnostic degrades to a no-op there
|
||||||
|
// rather than failing the build. Local (Xcode) builds keep it.
|
||||||
|
#if canImport(os)
|
||||||
|
import os
|
||||||
|
#endif
|
||||||
|
|
||||||
/// `LinuxProcess` represents a Linux process and is used to
|
/// `LinuxProcess` represents a Linux process and is used to
|
||||||
/// setup and control the full lifecycle for the process.
|
/// setup and control the full lifecycle for the process.
|
||||||
public final class LinuxProcess: Sendable {
|
public final class LinuxProcess: Sendable {
|
||||||
/// [Nucleic vendored patch] Diagnostic log for stdio stream-connection failures (see `setupIO`).
|
/// [Nucleic vendored patch] Diagnostic log for stdio stream-connection failures (see `setupIO`).
|
||||||
|
#if canImport(os)
|
||||||
static let nucleicIOLog = os.Logger(subsystem: "com.nucleic", category: "container-io")
|
static let nucleicIOLog = os.Logger(subsystem: "com.nucleic", category: "container-io")
|
||||||
|
#endif
|
||||||
|
|
||||||
/// The ID of the process. This is purely metadata for the caller.
|
/// The ID of the process. This is purely metadata for the caller.
|
||||||
public let id: String
|
public let id: String
|
||||||
@@ -191,12 +200,15 @@ extension LinuxProcess {
|
|||||||
// never wired — the agent's stdin is then never delivered (it hangs waiting for input) or
|
// never wired — the agent's stdin is then never delivered (it hangs waiting for input) or
|
||||||
// its stdout is never read ("no output, just a spinner"). Log that specific failure (Console
|
// its stdout is never read ("no output, just a spinner"). Log that specific failure (Console
|
||||||
// / `log show`, subsystem com.nucleic, category container-io) so a stall pinpoints the stream
|
// / `log show`, subsystem com.nucleic, category container-io) so a stall pinpoints the stream
|
||||||
// instead of proceeding silently. Log-only; behavior is unchanged.
|
// instead of proceeding silently. Log-only; behavior is unchanged. Guarded on `canImport(os)`
|
||||||
|
// (see the import) so a toolchain without the `os` overlay still builds.
|
||||||
|
#if canImport(os)
|
||||||
let configured = [self.ioSetup.stdin != nil, self.ioSetup.stdout != nil, self.ioSetup.stderr != nil]
|
let configured = [self.ioSetup.stdin != nil, self.ioSetup.stdout != nil, self.ioSetup.stderr != nil]
|
||||||
for (index, label) in [(0, "stdin"), (1, "stdout"), (2, "stderr")] where configured[index] && handles[index] == nil {
|
for (index, label) in [(0, "stdin"), (1, "stdout"), (2, "stderr")] where configured[index] && handles[index] == nil {
|
||||||
Self.nucleicIOLog.error(
|
Self.nucleicIOLog.error(
|
||||||
"setupIO[\(self.id, privacy: .public)]: \(label, privacy: .public) stream never connected from the guest — agent stdio will stall")
|
"setupIO[\(self.id, privacy: .public)]: \(label, privacy: .public) stream never connected from the guest — agent stdio will stall")
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Note: stdin relay is started separately via startStdinRelay() after
|
// Note: stdin relay is started separately via startStdinRelay() after
|
||||||
// the process has started, to avoid a deadlock where closeStdin is
|
// the process has started, to avoid a deadlock where closeStdin is
|
||||||
|
|||||||
Reference in New Issue
Block a user