IGameConfig: fix load-time race condition

As some public properties of `IGameConfig` are being set on the first
`Framework` tick, there was a short window that those properties were
null, which goes against the interface declaration.

This commit fixes that, by making those properties block for the full
initialization of the class.

A possible side effect is that a plugin that is set to block the game
from loading until it loads will now hang the game if it tries to access
the game configuration from its constructor, instead of throwing a
`NullReferenceException`. As it would mean that the plugin was buggy at
the first place and it would have sometimes failed to load anyway, it
might as well be a non-breaking change.
This commit is contained in:
Soreepeong 2024-02-20 15:37:54 +09:00
parent ac59f73b59
commit c27422384f
3 changed files with 126 additions and 23 deletions

View file

@ -10,6 +10,7 @@ using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Dalamud.Configuration.Internal;
using Dalamud.Data;
@ -697,6 +698,45 @@ public static class Util
Marshal.ThrowExceptionForHR(hr.Value);
}
/// <summary>
/// Calls <see cref="TaskCompletionSource.SetException(System.Exception)"/> if the task is incomplete.
/// </summary>
/// <param name="t">The task.</param>
/// <param name="ex">The exception to set.</param>
internal static void SetExceptionIfIncomplete(this TaskCompletionSource t, Exception ex)
{
if (t.Task.IsCompleted)
return;
try
{
t.SetException(ex);
}
catch
{
// ignore
}
}
/// <summary>
/// Calls <see cref="TaskCompletionSource.SetException(System.Exception)"/> if the task is incomplete.
/// </summary>
/// <typeparam name="T">The type of the result.</typeparam>
/// <param name="t">The task.</param>
/// <param name="ex">The exception to set.</param>
internal static void SetExceptionIfIncomplete<T>(this TaskCompletionSource<T> t, Exception ex)
{
if (t.Task.IsCompleted)
return;
try
{
t.SetException(ex);
}
catch
{
// ignore
}
}
/// <summary>
/// Print formatted GameObject Information to ImGui.
/// </summary>