Fix macOS launch crash from SkiaSharp mismatch and harden crash handler (#2115) (#2116)

- Pin SkiaSharp back to 3.119.4 in LibationUiBase to match Avalonia.Skia's
  expected native Skia milestone and restore the sk_fontmgr_ref_default export.
- Wrap BuildAvaloniaApp()?.SetupWithoutStarting() in Program.cs in try/catch to
  prevent InvalidOperationException ('Setup was already called on one of
  AppBuilder instances') when startup faults inside AppBuilder.Setup().
- Add TryShowFallbackAlert in Program.cs to output to stderr and trigger a
  native OS dialog (osascript display alert on macOS, MessageBoxW on Windows)
  when Avalonia cannot initialize its UI subsystem.
This commit is contained in:
William Tanksley Jr authored and GitHub committed 2026-10-26 20:56:01 -06:00
1 parent 9ab9343737
commit ed9c2cc409
2 files changed
+58 -2

No files matched your search

+57 -1
View File
@@ -146,7 +146,19 @@ static class Program
}
//Run setup if needed so that we can show the crash dialog
BuildAvaloniaApp()?.SetupWithoutStarting();
try
{
BuildAvaloniaApp()?.SetupWithoutStarting();
}
catch (Exception ex)
{
try
{
if (Configuration.Instance.SerilogInitialized)
Serilog.Log.Logger.Warning(ex, "Could not initialize Avalonia for crash dialog.");
}
catch { /* ignore */ }
}
try
{
@@ -154,10 +166,54 @@ static class Program
}
catch (Exception ex)
{
TryShowFallbackAlert(exception, crashLogFile, submittedToLogger);
Environment.FailFast("Fatal error displaying crash message", new AggregateException(ex, exception));
}
}
private static void TryShowFallbackAlert(Exception exception, string? crashLogFile, bool submittedToLogger)
{
var fatalMessage = StartupAssemblyBootstrap.GetFatalStartupMessage(
exception,
new FatalStartupMessage(
"Libation Crash",
$"""
Libation encountered a fatal error and must close.
{DescribeCrashLog(crashLogFile, submittedToLogger)}
"""));
try
{
Console.Error.WriteLine($"{fatalMessage.Title}: {fatalMessage.Body}");
Console.Error.WriteLine(exception);
}
catch { /* ignore */ }
if (Configuration.IsMacOs)
{
try
{
var escapedTitle = fatalMessage.Title.Replace("\\", "\\\\").Replace("\"", "\\\"");
var escapedMsg = $"{fatalMessage.Body}\n\n{exception.Message}".Replace("\\", "\\\\").Replace("\"", "\\\"");
var script = $"display alert \"{escapedTitle}\" message \"{escapedMsg}\" as critical buttons {{\"OK\"}} default button \"OK\"";
Process.Start(new ProcessStartInfo("osascript", ["-e", script]) { CreateNoWindow = true, UseShellExecute = false })?.WaitForExit(10000);
}
catch { /* ignore */ }
}
else if (Configuration.IsWindows)
{
try
{
MessageBoxW(IntPtr.Zero, $"{fatalMessage.Body}\r\n\r\n{exception.Message}", fatalMessage.Title, 0x10 /* MB_ICONERROR */);
}
catch { /* ignore */ }
}
}
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "MessageBoxW", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
private static extern int MessageBoxW(IntPtr hWnd, string text, string caption, uint type);
private static void DisplayErrorMessage(Exception exception, string? crashLogFile, bool submittedToLogger)
{
var dispatcher = new DispatcherFrame();
+1 -1
View File
@@ -12,7 +12,7 @@
<ItemGroup>
<!-- Rasterizes the Liberate column's icons. Kept on the same major version as the one
Avalonia.Skia resolves, so the Avalonia app doesn't get a mismatched native Skia. -->
<PackageReference Include="SkiaSharp" Version="4.153.1" />
<PackageReference Include="SkiaSharp" Version="3.119.4" />
</ItemGroup>
<ItemGroup>