From cecb09dcedd20300a6f68844d5372af70c933493 Mon Sep 17 00:00:00 2001
From: goat <16760685+goaaats@users.noreply.github.com>
Date: Tue, 16 Apr 2024 23:32:13 +0200
Subject: [PATCH] ioc: cancel all blocking Get()'s when unloading (#1772)
---
Dalamud/ServiceManager.cs | 11 +++++++++++
Dalamud/Service{T}.cs | 2 +-
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/Dalamud/ServiceManager.cs b/Dalamud/ServiceManager.cs
index bdc0918b0..75daf9187 100644
--- a/Dalamud/ServiceManager.cs
+++ b/Dalamud/ServiceManager.cs
@@ -43,6 +43,7 @@ internal static class ServiceManager
#endif
private static readonly TaskCompletionSource BlockingServicesLoadedTaskCompletionSource = new();
+ private static readonly CancellationTokenSource UnloadCancellationTokenSource = new();
private static ManualResetEvent unloadResetEvent = new(false);
@@ -107,6 +108,12 @@ internal static class ServiceManager
/// Gets task that gets completed when all blocking early loading services are done loading.
///
public static Task BlockingResolved { get; } = BlockingServicesLoadedTaskCompletionSource.Task;
+
+ ///
+ /// Gets a cancellation token that will be cancelled once Dalamud needs to unload, be it due to a failure state
+ /// during initialization or during regular operation.
+ ///
+ public static CancellationToken UnloadCancellationToken => UnloadCancellationTokenSource.Token;
///
/// Initializes Provided Services and FFXIVClientStructs.
@@ -374,6 +381,8 @@ internal static class ServiceManager
}
catch (Exception e)
{
+ UnloadCancellationTokenSource.Cancel();
+
Log.Error(e, "Failed resolving services");
try
{
@@ -401,6 +410,8 @@ internal static class ServiceManager
///
public static void UnloadAllServices()
{
+ UnloadCancellationTokenSource.Cancel();
+
var framework = Service.GetNullable(Service.ExceptionPropagationMode.None);
if (framework is { IsInFrameworkUpdateThread: false, IsFrameworkUnloading: false })
{
diff --git a/Dalamud/Service{T}.cs b/Dalamud/Service{T}.cs
index 165257ef5..a4d404e18 100644
--- a/Dalamud/Service{T}.cs
+++ b/Dalamud/Service{T}.cs
@@ -116,7 +116,7 @@ internal static class Service where T : IServiceType
#endif
if (!instanceTcs.Task.IsCompleted)
- instanceTcs.Task.Wait();
+ instanceTcs.Task.Wait(ServiceManager.UnloadCancellationToken);
return instanceTcs.Task.Result;
}