ioc: cancel all blocking Get()'s when unloading (#1772)

This commit is contained in:
goat 2024-04-16 23:32:13 +02:00 committed by GitHub
parent b1a8ec7615
commit cecb09dced
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 12 additions and 1 deletions

View file

@ -43,6 +43,7 @@ internal static class ServiceManager
#endif #endif
private static readonly TaskCompletionSource BlockingServicesLoadedTaskCompletionSource = new(); private static readonly TaskCompletionSource BlockingServicesLoadedTaskCompletionSource = new();
private static readonly CancellationTokenSource UnloadCancellationTokenSource = new();
private static ManualResetEvent unloadResetEvent = new(false); private static ManualResetEvent unloadResetEvent = new(false);
@ -108,6 +109,12 @@ internal static class ServiceManager
/// </summary> /// </summary>
public static Task BlockingResolved { get; } = BlockingServicesLoadedTaskCompletionSource.Task; public static Task BlockingResolved { get; } = BlockingServicesLoadedTaskCompletionSource.Task;
/// <summary>
/// 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.
/// </summary>
public static CancellationToken UnloadCancellationToken => UnloadCancellationTokenSource.Token;
/// <summary> /// <summary>
/// Initializes Provided Services and FFXIVClientStructs. /// Initializes Provided Services and FFXIVClientStructs.
/// </summary> /// </summary>
@ -374,6 +381,8 @@ internal static class ServiceManager
} }
catch (Exception e) catch (Exception e)
{ {
UnloadCancellationTokenSource.Cancel();
Log.Error(e, "Failed resolving services"); Log.Error(e, "Failed resolving services");
try try
{ {
@ -401,6 +410,8 @@ internal static class ServiceManager
/// </summary> /// </summary>
public static void UnloadAllServices() public static void UnloadAllServices()
{ {
UnloadCancellationTokenSource.Cancel();
var framework = Service<Framework>.GetNullable(Service<Framework>.ExceptionPropagationMode.None); var framework = Service<Framework>.GetNullable(Service<Framework>.ExceptionPropagationMode.None);
if (framework is { IsInFrameworkUpdateThread: false, IsFrameworkUnloading: false }) if (framework is { IsInFrameworkUpdateThread: false, IsFrameworkUnloading: false })
{ {

View file

@ -116,7 +116,7 @@ internal static class Service<T> where T : IServiceType
#endif #endif
if (!instanceTcs.Task.IsCompleted) if (!instanceTcs.Task.IsCompleted)
instanceTcs.Task.Wait(); instanceTcs.Task.Wait(ServiceManager.UnloadCancellationToken);
return instanceTcs.Task.Result; return instanceTcs.Task.Result;
} }