Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions src/BuildMonitor.Tests/Launcher/HeadLocatorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,29 @@ public async Task RidsStartWithTheExactOne()
await Assert.That(rids[0]).IsEqualTo(RuntimeInformation.RuntimeIdentifier);
await Assert.That(rids.Count).IsGreaterThanOrEqualTo(1);
}

/// <summary>
/// The probe for a musl RID is that RID alone. The linux-{arch} candidate after it names the
/// glibc head, which cannot start on musl: the launcher would wait out its timeout for a tray
/// that was never going to answer, rather than say there is no head for the machine.
/// </summary>
[Test]
[Arguments("linux-musl-x64")]
[Arguments("linux-musl-arm64")]
public async Task MuslProbesItsOwnRidAndNothingElse(string runtimeIdentifier)
{
var rids = HeadLocator.Rids(runtimeIdentifier).ToList();
await Assert.That(rids).IsEquivalentTo([runtimeIdentifier]);
}

/// <summary>
/// Everywhere else the synthesised RID still follows the framework's own.
/// </summary>
[Test]
public async Task OtherRidsStillFallBackToTheSynthesisedRid()
{
var rids = HeadLocator.Rids("some-rid").ToList();
await Assert.That(rids.Count).IsGreaterThan(1);
await Assert.That(rids[0]).IsEqualTo("some-rid");
}
}
27 changes: 23 additions & 4 deletions src/BuildMonitor/HeadLocator.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
/// <summary>
/// Finds the tray executable for this machine under heads/{rid}. The exact RID is tried first,
/// then the plain os-arch one, the same order DiffEngine resolves its native renderers in, so
/// a linux-musl-x64 machine misses rather than starting a glibc build.
/// then the plain os-arch one, the same order DiffEngine resolves its native renderers in.
/// <para>
/// A musl RID is the exception and is tried alone. No head is built for musl, and the os-arch
/// one after it is linux-{arch}, the glibc build: found, it would be started and never answer,
/// so a linux-musl-x64 machine has to miss here to be told there is no head for it.
/// </para>
/// </summary>
static class HeadLocator
{
Expand Down Expand Up @@ -31,9 +35,24 @@ static class HeadLocator
return null;
}

public static IEnumerable<string> Rids()
public static IEnumerable<string> Rids() =>
Rids(RuntimeInformation.RuntimeIdentifier);

public static IEnumerable<string> Rids(string runtimeIdentifier)
{
yield return RuntimeInformation.RuntimeIdentifier;
// The exact RID first. On Alpine that is linux-musl-x64, which we do not ship, so the
// probe misses and the launcher says there is no head for this machine.
yield return runtimeIdentifier;

// And nothing else, or the synthesised RID below undoes that: linux-{arch} is the glibc
// build, an apphost that cannot start on musl. The launcher would start it detached, wait
// out its timeout and report a tray that did not answer, when the truth is that no head
// is built for this machine.
if (runtimeIdentifier.Contains("-musl-", StringComparison.Ordinal))
{
yield break;
}

var architecture = RuntimeInformation.OSArchitecture switch
{
Architecture.X64 => "x64",
Expand Down
Loading