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; }