Skip to content

Commit b1ad848

Browse files
committed
* generate crash reports on unhandled exceptions after startup
* make ACTcpClient.SendPacketUdp public
1 parent 95c1ee4 commit b1ad848

File tree

4 files changed

+38
-23
lines changed

4 files changed

+38
-23
lines changed

AssettoServer.Shared/Services/CriticalBackgroundService.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
using Microsoft.Extensions.Hosting;
2-
using Serilog;
32

43
namespace AssettoServer.Shared.Services;
54

65
public abstract class CriticalBackgroundService : IHostedService, IDisposable
76
{
7+
public static event UnhandledExceptionEventHandler? UnhandledException;
8+
89
private readonly CancellationTokenSource _stoppingCts = new();
910
private readonly IHostApplicationLifetime _applicationLifetime;
1011

@@ -30,7 +31,7 @@ public Task StartAsync(CancellationToken cancellationToken)
3031
{
3132
if (t.Exception != null)
3233
{
33-
Log.Fatal(t.Exception, "Error executing critical background service");
34+
UnhandledException?.Invoke(this, new UnhandledExceptionEventArgs(t.Exception, true));
3435
_applicationLifetime.StopApplication();
3536
}
3637
}, _stoppingCts.Token);

AssettoServer/CrashReportHelper.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Text.RegularExpressions;
88
using AssettoServer.Server.Configuration;
99
using Scriban;
10+
using Serilog;
1011

1112
namespace AssettoServer;
1213

@@ -18,6 +19,28 @@ private class Attachment
1819
public string? Type { get; init; }
1920
public required string Content { get; init; }
2021
}
22+
23+
public static void HandleFatalException(Exception ex)
24+
{
25+
Log.Fatal(ex, "Fatal exception occurred");
26+
string? crashReportPath = null;
27+
28+
var configLocations = Program.ConfigurationLocations;
29+
if (configLocations != null)
30+
{
31+
try
32+
{
33+
crashReportPath = GenerateCrashReport(configLocations, ex);
34+
}
35+
catch (Exception ex2)
36+
{
37+
Log.Error(ex2, "Error writing crash report");
38+
}
39+
}
40+
41+
Log.CloseAndFlush();
42+
ExceptionHelper.PrintExceptionHelp(ex, Program.IsContentManager, crashReportPath);
43+
}
2144

2245
public static string GenerateCrashReport(ConfigurationLocations locations, Exception exception)
2346
{

AssettoServer/Network/Tcp/ACTcpClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ public void SendPacket<TPacket>(TPacket packet) where TPacket : IOutgoingNetwork
259259
}
260260
}
261261

262-
internal void SendPacketUdp<TPacket>(in TPacket packet) where TPacket : IOutgoingNetworkPacket
262+
public void SendPacketUdp<TPacket>(in TPacket packet) where TPacket : IOutgoingNetworkPacket
263263
{
264264
if (UdpEndpoint == null) return;
265265

AssettoServer/Program.cs

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Text;
77
using System.Threading;
88
using System.Threading.Tasks;
9+
using AssettoServer.Shared.Services;
910
using AssettoServer.Utils;
1011
using Autofac.Extensions.DependencyInjection;
1112
using CommandLine;
@@ -61,7 +62,9 @@ private class StartOptions
6162
public string? EntryListPath { get; init; }
6263
}
6364

64-
public static bool IsContentManager;
65+
public static bool IsContentManager { get; private set; }
66+
public static ConfigurationLocations? ConfigurationLocations { get; private set; }
67+
6568
private static bool _loadPluginsFromWorkdir;
6669
private static bool _generatePluginConfigs;
6770
private static TaskCompletionSource<StartOptions> _restartTask = new();
@@ -100,7 +103,8 @@ internal static async Task Main(string[] args)
100103
string logPrefix = string.IsNullOrEmpty(options.Preset) ? "log" : options.Preset;
101104
Logging.CreateLogger(logPrefix, IsContentManager, options.Preset, options.UseVerboseLogging);
102105

103-
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
106+
AppDomain.CurrentDomain.UnhandledException += UnhandledException;
107+
CriticalBackgroundService.UnhandledException += UnhandledException;
104108
Log.Information("AssettoServer {Version}", ThisAssembly.AssemblyInformationalVersion);
105109
if (IsContentManager)
106110
{
@@ -150,11 +154,11 @@ private static async Task RunServerAsync(
150154
bool useVerboseLogging,
151155
CancellationToken token = default)
152156
{
153-
var configLocations = ConfigurationLocations.FromOptions(preset, serverCfgPath, entryListPath);
157+
ConfigurationLocations = ConfigurationLocations.FromOptions(preset, serverCfgPath, entryListPath);
154158

155159
try
156160
{
157-
var config = new ACServerConfiguration(preset, configLocations, _loadPluginsFromWorkdir, _generatePluginConfigs);
161+
var config = new ACServerConfiguration(preset, ConfigurationLocations, _loadPluginsFromWorkdir, _generatePluginConfigs);
158162

159163
string logPrefix = string.IsNullOrEmpty(preset) ? "log" : preset;
160164
Logging.CreateLogger(logPrefix, IsContentManager, preset, useVerboseLogging, config.Extra.RedactIpAddresses, config.Extra.LokiSettings);
@@ -191,26 +195,13 @@ private static async Task RunServerAsync(
191195
}
192196
catch (Exception ex)
193197
{
194-
Log.Fatal(ex, "Error starting server");
195-
string? crashReportPath = null;
196-
try
197-
{
198-
crashReportPath = CrashReportHelper.GenerateCrashReport(configLocations, ex);
199-
}
200-
catch (Exception ex2)
201-
{
202-
Log.Error(ex2, "Error writing crash report");
203-
}
204-
await Log.CloseAndFlushAsync();
205-
ExceptionHelper.PrintExceptionHelp(ex, IsContentManager, crashReportPath);
198+
CrashReportHelper.HandleFatalException(ex);
206199
}
207200
}
208201

209-
private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs args)
202+
private static void UnhandledException(object sender, UnhandledExceptionEventArgs args)
210203
{
211-
Log.Fatal((Exception)args.ExceptionObject, "Unhandled exception occurred");
212-
Log.CloseAndFlush();
213-
Environment.Exit(1);
204+
CrashReportHelper.HandleFatalException((Exception)args.ExceptionObject);
214205
}
215206

216207
private static void SetupFluentValidation()

0 commit comments

Comments
 (0)