Cleaner crash report workflow
MODIFY
WalletWasabi.Fluent.Desktop/Program.cs
WalletWasabi.Fluent.Desktop/Program.cs
@@ -31,7 +31,6 @@ namespace WalletWasabi.Fluent.Desktop
// yet and stuff might break.
public static int Main(string[] args)
{
- int exitCode = 0;
bool guiStarted = false;
SingleInstanceChecker? singleInstanceChecker = null;
CrashReporter crashReporter = new();
@@ -52,11 +51,13 @@ namespace WalletWasabi.Fluent.Desktop
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
- if (crashReporter.TryProcessCliArgs(args))
+ if (crashReporter.ProcessCliArgs(args) is { } exceptionToReport)
{
- Console.WriteLine("TODO Implement crash reporting.");
+ // Show the exception
+ Console.WriteLine($"TODO Implement crash reporting. {exceptionToReport}");
}
-
+ else
+ {
if (args.Length != 0)
{
ProcessCliCommands(Global, args);
@@ -70,19 +71,15 @@ namespace WalletWasabi.Fluent.Desktop
.StartWithClassicDesktopLifetime(args);
}
}
+ }
catch (OperationCanceledException ex)
{
Logger.LogDebug(ex);
}
catch (Exception ex)
- {
- exitCode = 1;
- Logger.LogCritical(ex);
-
- if (guiStarted)
{
crashReporter.SetException(ex);
- }
+ Logger.LogCritical(ex);
}
TerminateService.Terminate();
@@ -95,12 +92,15 @@ namespace WalletWasabi.Fluent.Desktop
AppDomain.CurrentDomain.UnhandledException -= CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException -= TaskScheduler_UnobservedTaskException;
+ if (guiStarted)
+ {
// Trigger the CrashReport process.
crashReporter.TryInvokeIfRequired();
+ }
Logger.LogSoftwareStopped("Wasabi");
- return exitCode;
+ return crashReporter.HadException ? 1 : 0;
}
private static (UiConfig uiConfig, Config config) LoadOrCreateConfigs(string dataDir)

MODIFY
WalletWasabi.Fluent/CrashReport/CrashReporter.cs
WalletWasabi.Fluent/CrashReport/CrashReporter.cs
@@ -8,15 +8,24 @@ namespace WalletWasabi.Fluent.CrashReport
{
public class CrashReporter
{
- private const int MaxRecursiveCalls = 5;
+ private const int MaxRecursiveCalls = 3;
public int Attempts { get; private set; }
- public string? Base64ExceptionString { get; private set; } = null;
+ private string? Base64ExceptionString { get; set; } = null;
+
+ /// <summary>
+ /// The current Wasabi instance had an exception.
+ /// </summary>
public bool HadException { get; private set; }
+
public SerializableException? SerializedException { get; private set; }
+ /// <summary>
+ /// Call this right before the end of the application. It will call another Wasabi instance in crash report mode if there is something to report.
+ /// The exception can be set by the CLI arguments by calling <see cref="ProcessCliArgs(string[])"/> or <see cref="SetException(Exception)"/>.
+ /// </summary>
public void TryInvokeIfRequired()
{
- if (!HadException)
+ if (SerializedException is null)
{
return;
}
@@ -55,11 +64,11 @@ namespace WalletWasabi.Fluent.CrashReport
return $"crashreport -attempt=\"{Attempts + 1}\" -exception=\"{Base64ExceptionString}\"";
}
- public bool TryProcessCliArgs(string[] args)
+ public SerializableException? ProcessCliArgs(string[] args)
{
if (args.Length < 3)
{
- return false;
+ return null;
}
if (args[0].Contains("crashreport") && args[1].Contains("-attempt=") && args[2].Contains("-exception="))
@@ -69,13 +78,11 @@ namespace WalletWasabi.Fluent.CrashReport
var exceptionString = args[2].Split("=", StringSplitOptions.RemoveEmptyEntries)[1].Trim('"');
Attempts = int.Parse(attemptString);
- Base64ExceptionString = exceptionString;
- SerializedException = SerializableException.FromBase64String(exceptionString);
- return true;
+ return SerializableException.FromBase64String(exceptionString);
}
- return false;
+ return null;
}
/// <summary>

MODIFY
WalletWasabi.Tests/UnitTests/Clients/CrashReportTests.cs
WalletWasabi.Tests/UnitTests/Clients/CrashReportTests.cs
@@ -31,8 +31,8 @@ namespace WalletWasabi.Tests.UnitTests.Clients
CrashReporter reporting = new();
// Args are split by space and passed to Main IRL.
- Assert.True(reporting.TryProcessCliArgs(args.Split(' ')));
- Assert.Equal(reporting.SerializedException, ex.ToSerializableException());
+ var exceptionFromCli = reporting.ProcessCliArgs(args.Split(' '));
+ Assert.Equal(exceptionFromCli, ex.ToSerializableException());
}
}
}

Cleaner crash report workflow