Fix async plugin load and show full profiler (#898)

This commit is contained in:
kizer 2022-06-26 02:34:40 +09:00 committed by GitHub
parent 86b5eec493
commit c7dc8c81f4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 404 additions and 248 deletions

View file

@ -314,13 +314,13 @@ internal partial class PluginManager : IDisposable
// Dev plugins should load first.
pluginDefs.InsertRange(0, devPluginDefs);
Task LoadPluginOnBoot(string logPrefix, PluginDef pluginDef)
async Task LoadPluginOnBoot(string logPrefix, PluginDef pluginDef)
{
using (Timings.Start($"{pluginDef.DllFile.Name}: {logPrefix}Boot"))
{
try
{
return this.LoadPluginAsync(
await this.LoadPluginAsync(
pluginDef.DllFile,
pluginDef.Manifest,
PluginLoadReason.Boot,
@ -336,8 +336,6 @@ internal partial class PluginManager : IDisposable
Log.Error(ex, "{0}: During boot plugin load, an unexpected error occurred", logPrefix);
}
}
return Task.CompletedTask;
}
void LoadPluginsSync(string logPrefix, IEnumerable<PluginDef> pluginDefsList)
@ -350,7 +348,8 @@ internal partial class PluginManager : IDisposable
{
return Task.WhenAll(
pluginDefsList
.Select(pluginDef => LoadPluginOnBoot(logPrefix, pluginDef))
.Select(pluginDef => Task.Run(Timings.AttachTimingHandle(
() => LoadPluginOnBoot(logPrefix, pluginDef))))
.ToArray());
}
@ -394,15 +393,15 @@ internal partial class PluginManager : IDisposable
TaskContinuationOptions.RunContinuationsAsynchronously)
.Unwrap()
.ContinueWith(
_ => Service<Framework>.Get().RunOnTick(() =>
{
LoadPluginsSync(
_ => Service<Framework>.Get().RunOnTick(
() => LoadPluginsSync(
"DrawAvailableSync",
syncPlugins.Where(def => def.Manifest?.LoadRequiredState is 0 or null));
return LoadPluginsAsync(
"DrawAvailableAsync",
asyncPlugins.Where(def => def.Manifest?.LoadRequiredState is 0 or null));
}))
syncPlugins.Where(def => def.Manifest?.LoadRequiredState is 0 or null))))
.Unwrap()
.ContinueWith(
_ => LoadPluginsAsync(
"DrawAvailableAsync",
asyncPlugins.Where(def => def.Manifest?.LoadRequiredState is 0 or null)))
.Unwrap());
// Save signatures when all plugins are done loading, successful or not.
@ -427,33 +426,16 @@ internal partial class PluginManager : IDisposable
/// <summary>
/// Reload all loaded plugins.
/// </summary>
public void ReloadAllPlugins()
/// <returns>A task.</returns>
public Task ReloadAllPluginsAsync()
{
var aggregate = new List<Exception>();
lock (this.pluginListLock)
{
foreach (var plugin in this.InstalledPlugins)
{
if (plugin.IsLoaded)
{
try
{
plugin.Reload();
}
catch (Exception ex)
{
Log.Error(ex, "Error during reload all");
aggregate.Add(ex);
}
}
}
}
if (aggregate.Any())
{
throw new AggregateException(aggregate);
return Task.WhenAll(this.InstalledPlugins
.Where(x => x.IsLoaded)
.ToList()
.Select(x => Task.Run(async () => await x.ReloadAsync()))
.ToList());
}
}
@ -706,10 +688,7 @@ internal partial class PluginManager : IDisposable
if (plugin.IsDisabled)
plugin.Enable();
// Await for things that plugin just require
_ = await Service<SigScanner>.GetAsync();
plugin.Load(reason);
await plugin.LoadAsync(reason);
}
catch (InvalidPluginException)
{
@ -1004,7 +983,7 @@ internal partial class PluginManager : IDisposable
Thread.Sleep(500);
// Let's indicate "installer" here since this is supposed to be a fresh install
plugin.Load(PluginLoadReason.Installer);
plugin.LoadAsync(PluginLoadReason.Installer).Wait();
}
/// <summary>

View file

@ -124,7 +124,7 @@ internal class LocalDevPlugin : LocalPlugin, IDisposable
var current = Interlocked.Increment(ref this.reloadCounter);
Task.Delay(500).ContinueWith(
_ =>
async _ =>
{
if (this.fileWatcherTokenSource.IsCancellationRequested)
{
@ -148,7 +148,7 @@ internal class LocalDevPlugin : LocalPlugin, IDisposable
try
{
this.Reload();
await this.ReloadAsync();
notificationManager.AddNotification($"The DevPlugin '{this.Name} was reloaded successfully.", "Plugin reloaded!", NotificationType.Success);
}
catch (Exception ex)

View file

@ -2,7 +2,7 @@ using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Dalamud.Configuration.Internal;
using Dalamud.Game;
using Dalamud.Game.Gui.Dtr;
@ -160,7 +160,7 @@ internal class LocalPlugin : IDisposable
public PluginState State { get; protected set; }
/// <summary>
/// Gets the AssemblyName plugin, populated during <see cref="Load(PluginLoadReason, bool)"/>.
/// Gets the AssemblyName plugin, populated during <see cref="LoadAsync"/>.
/// </summary>
/// <returns>Plugin type.</returns>
public AssemblyName? AssemblyName { get; private set; }
@ -225,7 +225,8 @@ internal class LocalPlugin : IDisposable
/// </summary>
/// <param name="reason">The reason why this plugin is being loaded.</param>
/// <param name="reloading">Load while reloading.</param>
public void Load(PluginLoadReason reason, bool reloading = false)
/// <returns>A task.</returns>
public async Task LoadAsync(PluginLoadReason reason, bool reloading = false)
{
var startInfo = Service<DalamudStartInfo>.Get();
var configuration = Service<DalamudConfiguration>.Get();
@ -334,7 +335,7 @@ internal class LocalPlugin : IDisposable
this.DalamudInterface = new DalamudPluginInterface(this.pluginAssembly.GetName().Name!, this.DllFile, reason, this.IsDev);
var ioc = Service<ServiceContainer>.Get();
this.instance = ioc.CreateAsync(this.pluginType, this.DalamudInterface).GetAwaiter().GetResult() as IDalamudPlugin;
this.instance = await ioc.CreateAsync(this.pluginType, this.DalamudInterface) as IDalamudPlugin;
if (this.instance == null)
{
this.State = PluginState.LoadError;
@ -423,7 +424,8 @@ internal class LocalPlugin : IDisposable
/// <summary>
/// Reload this plugin.
/// </summary>
public void Reload()
/// <returns>A task.</returns>
public async Task ReloadAsync()
{
this.Unload(true);
@ -431,7 +433,7 @@ internal class LocalPlugin : IDisposable
var dtr = Service<DtrBar>.Get();
dtr.HandleRemovedNodes();
this.Load(PluginLoadReason.Reload, true);
await this.LoadAsync(PluginLoadReason.Reload, true);
}
/// <summary>