Merge nucleic/olive-jade-civet-rznt into dev
This commit is contained in:
@@ -89,7 +89,9 @@ internal static class Program
|
||||
}
|
||||
else
|
||||
{
|
||||
ProbeSession(types, ArgValue(args, "--session-name") ?? "nucleic-spike");
|
||||
ProbeSession(
|
||||
types, ArgValue(args, "--session-name") ?? "nucleic-spike",
|
||||
keep: args.Contains("--keep"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,7 +357,7 @@ internal static class Program
|
||||
///
|
||||
/// Leaves the session running on purpose: whether it outlives this process is the other half
|
||||
/// of the same question. Tear it down with `wslc` when you are done.
|
||||
private static void ProbeSession(Type[] types, string name)
|
||||
private static void ProbeSession(Type[] types, string name, bool keep)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"live probe (creates session '{name}'):");
|
||||
@@ -411,29 +413,83 @@ internal static class Program
|
||||
}
|
||||
}
|
||||
Console.WriteLine(" → CONSTRUCTED — the constructor did NOT refuse.");
|
||||
Console.WriteLine();
|
||||
// Be honest about what this does and does not show. A constructed object is not proof
|
||||
// of attachment: construction may simply be lazy, and WSLC_E_SESSION_RESERVED clearly
|
||||
// fires under SOME condition or it would not exist in wslc.idl. The compat surface has
|
||||
// no enumeration, so identity cannot be settled from inside this process.
|
||||
Console.WriteLine(" This does NOT by itself prove it re-adopted the first session —");
|
||||
Console.WriteLine(" construction may be lazy, and WSLC_E_SESSION_RESERVED exists in");
|
||||
Console.WriteLine(" wslc.idl, so it fires under some condition. The compat surface has");
|
||||
Console.WriteLine(" no enumeration, so identity cannot be settled from in here.");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(" DECISIVE CHECK — run this now: wslc session ls");
|
||||
Console.WriteLine($" ONE session named '{name}' → it attached; the SESSION half of");
|
||||
Console.WriteLine(" §2.3 reattach may not need the");
|
||||
Console.WriteLine(" internal COM interface after all.");
|
||||
Console.WriteLine($" TWO sessions named '{name}' → it did not; two VMs are running and");
|
||||
Console.WriteLine(" the name is not an identity.");
|
||||
Console.WriteLine(" Either way the CONTAINER half of D13 is unaffected: there is still");
|
||||
Console.WriteLine(" no way to enumerate containers on the compat surface.");
|
||||
IdentityTest(sessionType, first, second);
|
||||
}
|
||||
Console.WriteLine();
|
||||
if (keep)
|
||||
{
|
||||
Console.WriteLine(" --keep: session(s) left running, so you can check whether they "
|
||||
+ "outlive this process (the other half of the §2.3 question).");
|
||||
Console.WriteLine(" Tear down with `wsl --shutdown` — note that `wslc.exe` is NOT on "
|
||||
+ "PATH by default; it lives beside wsl.exe (try `C:\\Program Files\\WSL\\wslc.exe`).");
|
||||
}
|
||||
else
|
||||
{
|
||||
Terminate(sessionType, first, "first");
|
||||
Console.WriteLine(" (pass --keep to leave sessions running instead)");
|
||||
}
|
||||
}
|
||||
|
||||
/// Decide whether the second same-named `Session` re-adopted the first, using ONLY the compat
|
||||
/// SDK — no CLI, which matters because `wslc.exe` is not on PATH by default.
|
||||
///
|
||||
/// The trick: terminate the FIRST session and see whether the SECOND dies with it. A read that
|
||||
/// worked before termination and fails after is the same underlying session answering; a read
|
||||
/// that keeps working means two independent sessions were running all along. `GetImages` is
|
||||
/// the cheapest read on the surface and mutates nothing.
|
||||
private static void IdentityTest(Type sessionType, object first, object second)
|
||||
{
|
||||
var getImages = sessionType.GetMethods(Public)
|
||||
.FirstOrDefault(m => !m.IsStatic && m.Name == "GetImages" && m.GetParameters().Length == 0);
|
||||
if (getImages is null) { Console.WriteLine(" (no GetImages — cannot test identity)"); return; }
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(" session left running — `wslc session ls`; whether it outlives this "
|
||||
+ "process is the other half of the §2.3 reattach question.");
|
||||
Console.WriteLine(" identity test: terminate the FIRST, then read from the SECOND");
|
||||
if (!Reads(getImages, second, out var before))
|
||||
{
|
||||
Console.WriteLine($" inconclusive — the second session already fails to read: {before}");
|
||||
return;
|
||||
}
|
||||
Console.WriteLine(" second reads ok before termination");
|
||||
|
||||
if (!Terminate(sessionType, first, "first")) return;
|
||||
// The service tears a VM down asynchronously; give it a moment before concluding.
|
||||
Thread.Sleep(3000);
|
||||
|
||||
if (Reads(getImages, second, out var after))
|
||||
{
|
||||
Console.WriteLine(" second STILL reads ok after the first was terminated");
|
||||
Console.WriteLine(" → SEPARATE SESSIONS. The name is not an identity: two VMs were "
|
||||
+ "running. D13 stands — reattach needs IWSLCSessionManager::OpenSessionByName.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($" second now fails: {after}");
|
||||
Console.WriteLine(" → SAME SESSION. Constructing over an existing name RE-ADOPTS it, "
|
||||
+ "so the session half of §2.3 reattach is reachable from the compat surface and "
|
||||
+ "D13's reattach row softens (the container half is unaffected — still no "
|
||||
+ "enumeration).");
|
||||
}
|
||||
}
|
||||
|
||||
private static bool Reads(MethodInfo getImages, object session, out string detail)
|
||||
{
|
||||
try { getImages.Invoke(session, null); detail = "ok"; return true; }
|
||||
catch (TargetInvocationException e) { detail = Describe(e.InnerException); return false; }
|
||||
catch (Exception e) { detail = Describe(e); return false; }
|
||||
}
|
||||
|
||||
private static bool Terminate(Type sessionType, object session, string which)
|
||||
{
|
||||
var terminate = sessionType.GetMethods(Public)
|
||||
.FirstOrDefault(m => !m.IsStatic && m.Name == "Terminate" && m.GetParameters().Length == 0);
|
||||
if (terminate is null) { Console.WriteLine(" (no Session.Terminate)"); return false; }
|
||||
try { terminate.Invoke(session, null); Console.WriteLine($" {which} session terminated"); return true; }
|
||||
catch (TargetInvocationException e)
|
||||
{
|
||||
Console.WriteLine($" {which} Terminate() threw {Describe(e.InnerException)}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static object? CreateSession(
|
||||
|
||||
Reference in New Issue
Block a user