Launcher, CLI: no native crash capture, they ship neither libstridecrash nor the reporter

This commit is contained in:
Virgile Bello
2026-10-01 01:48:51 +09:00
parent 9babe77440
commit cbbbeb4a5d
4 changed files with 9 additions and 11 deletions
+2 -2
View File
@@ -19,14 +19,14 @@ There are two kinds of crash. A **managed** unhandled exception can be caught in
## What's covered
Native capture uses two supported mechanisms. The **GUI hosts** (GameStudio, Launcher, CLI) arm the native trigger `libstridecrash`, which spawns the reporter to capture out of process — **Windows only** for now. The **asset compiler** arms the runtime's own `createdump` and adopts the minidump after the build — **all platforms**. Managed capture is cross-platform everywhere.
Native capture uses two supported mechanisms. The **GUI host** GameStudio arms the native trigger `libstridecrash`, which spawns the reporter to capture out of process — **Windows only** for now. The **asset compiler** arms the runtime's own `createdump` and adopts the minidump after the build — **all platforms**. Managed capture is cross-platform everywhere. The Launcher and the CLI capture managed crashes only: they ship neither `libstridecrash` nor the reporter.
| Crash kind | Covered? | How it's handled |
|---|---|---|
| Managed unhandled exception | ✅ everywhere | GameStudio gathers its context (session, opened assets, undo history, GPU, breadcrumbs), saves it with a scrubbed triage dump and hands it to the reporter, blocking until it closes (see the reporter row). The Launcher shows its own minimal in-process window. The asset compiler is headless: it stores the crash and, at end of build, sends on CI or points at `stride crash send` — and a build triggered from GameStudio surfaces it in that GameStudio via the reporter (see Routing below). The CLI saves it and prints a `stride crash send` hint. |
| Native access violation (AV) | ✅ Windows | **GUI hosts:** the native trigger spawns the reporter, which writes the dump from outside the frozen process and — attended — shows it; unattended it saves silently. **Compiler:** `createdump` writes the dump, a post-build `crash-adopt` step folds it into the store, surfaced in the triggering GameStudio or via a `stride crash send` hint for a VS/CLI build. |
| Slave-process crash (compiler) | ✅ everywhere | Isolated slave build processes inherit the master's `createdump` env and write into the shared dump dir; the master's post-build `crash-adopt` collects them. |
| Native crash on Linux / macOS | ⚠️ compiler only | The compiler arms `createdump` (master + inherited slaves) and adopts each minidump into the store. GameStudio / Launcher / CLI aren't armed there yet — that gap closes when the runtime lets a user-launched app self-arm `createdump` (see below). |
| Native crash on Linux / macOS | ⚠️ compiler only | The compiler arms `createdump` (master + inherited slaves) and adopts each minidump into the store. GameStudio isn't armed there yet — that gap closes when the runtime lets a user-launched app self-arm `createdump` (see below). |
| Stack overflow | ⚠️ compiler only | No stack to run the in-process trigger, so the GUI hosts miss it; the compiler's `createdump` covers it. |
| Non-AV native fault (div-by-zero, illegal instruction) | ⚠️ compiler only | The trigger filters to access violations; the compiler's `createdump` covers the rest. |
| NativeAOT native crash | ❌ | Relies on WER / `createdump` (the GUI hosts' trigger is JIT/CoreCLR only). |
@@ -22,7 +22,8 @@ namespace Stride.CrashReport
private static bool installed;
/// <summary>
/// Arms native-crash capture for <paramref name="applicationName"/> (e.g. "GameStudio", "Launcher", "Cli").
/// Arms native-crash capture for <paramref name="applicationName"/> (e.g. "GameStudio"). The host must ship
/// libstridecrash and a reporter (the Launcher and the CLI don't, so they don't call it).
/// Safe to call once at startup; later calls are ignored. Off-Windows, under NativeAOT, or when
/// STRIDE_CRASH_MODE=off, it does nothing.
/// </summary>
@@ -272,8 +273,7 @@ namespace Stride.CrashReport
// In a real install the reporter is the Stride.CrashReporter package in the NuGet global store, its publish
// tree under tools/. Only the version this library was built for (CrashReporterVersion, baked by the csproj)
// is launched: Game Studio and the asset compiler depend on exactly that one; a host without the dependency
// (Launcher, CLI) captures natively only if some engine install left it there. Probes the store directly, no
// is launched: Game Studio and the asset compiler depend on exactly that one. Probes the store directly, no
// NuGet assemblies in this minimal library. Best-effort: any failure just means "no reporter".
private static string FindReporterInStore()
{
+2 -3
View File
@@ -6,9 +6,8 @@ using System.Diagnostics;
using System.Reflection;
using Stride.Cli.Core;
// Arm native access-violation capture before anything runs (native crashes kill the process before any managed
// handler can react). A no-op off Windows, under NativeAOT, or when STRIDE_CRASH_MODE=off.
Stride.CrashReport.NativeCrashReporting.Install("Cli");
// No native crash capture (NativeCrashReporting.Install): the CLI ships neither libstridecrash nor the reporter.
// Managed crashes go through CliCrashHandler.
var manager = new StrideVersionManager();
+2 -3
View File
@@ -28,10 +28,9 @@ internal static class Launcher
[STAThread]
public static LauncherErrorCode Main(string[] args)
{
// Managed crashes only, reported in process. No native crash capture (NativeCrashReporting.Install): the
// launcher ships neither libstridecrash nor the reporter.
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
// The managed handler above can't see a native access violation — it kills the process first. Arm the
// native handler so such a crash is captured and offered to the reporter too.
Stride.CrashReport.NativeCrashReporting.Install("Launcher");
try
{
var arguments = ProcessArguments(args);