fix: prevent some deadlocks in profile management code

We can never load/unload plugins synchronously, since they might need to get back on framework thread to unload.
Also fixes an issue wherein applying might have gotten stuck if an unload threw an exception.
This commit is contained in:
goat 2023-06-20 21:55:31 +02:00
parent da8bbf5a28
commit c3fe41640e
No known key found for this signature in database
GPG key ID: 49E2AA8C6A76498B
7 changed files with 107 additions and 88 deletions

View file

@ -119,7 +119,7 @@ internal class ProfileManagerWidget
var isEnabled = profile.IsEnabled;
if (ImGuiComponents.ToggleButton($"###toggleButton{profile.Guid}", ref isEnabled))
{
Task.Run(() => profile.SetState(isEnabled))
Task.Run(() => profile.SetStateAsync(isEnabled))
.ContinueWith(this.installer.DisplayErrorContinuation, Locs.ErrorCouldNotChangeState);
}
@ -228,9 +228,7 @@ internal class ProfileManagerWidget
if (ImGui.Selectable($"{plugin.Manifest.Name}###selector{plugin.Manifest.InternalName}"))
{
// TODO this sucks
profile.AddOrUpdate(plugin.Manifest.InternalName, true, false);
Task.Run(() => profman.ApplyAllWantStates())
Task.Run(() => profile.AddOrUpdateAsync(plugin.Manifest.InternalName, true, false))
.ContinueWith(this.installer.DisplayErrorContinuation, Locs.ErrorCouldNotChangeState);
}
}
@ -273,8 +271,12 @@ internal class ProfileManagerWidget
this.Reset();
// DeleteProfile() is sync, it doesn't apply and we are modifying the plugins collection. Will throw below when iterating
profman.DeleteProfile(profile);
Task.Run(() => profman.ApplyAllWantStates())
// TODO: DeleteProfileAsync should probably apply as well
Task.Run(async () =>
{
await profman.DeleteProfileAsync(profile);
await profman.ApplyAllWantStatesAsync();
})
.ContinueWith(t =>
{
this.installer.DisplayErrorContinuation(t, Locs.ErrorCouldNotChangeState);
@ -300,7 +302,7 @@ internal class ProfileManagerWidget
var isEnabled = profile.IsEnabled;
if (ImGuiComponents.ToggleButton($"###toggleButton{profile.Guid}", ref isEnabled))
{
Task.Run(() => profile.SetState(isEnabled))
Task.Run(() => profile.SetStateAsync(isEnabled))
.ContinueWith(this.installer.DisplayErrorContinuation, Locs.ErrorCouldNotChangeState);
}
@ -391,7 +393,7 @@ internal class ProfileManagerWidget
var enabled = plugin.IsEnabled;
if (ImGui.Checkbox($"###{this.editingProfileGuid}-{plugin.InternalName}", ref enabled))
{
Task.Run(() => profile.AddOrUpdate(plugin.InternalName, enabled))
Task.Run(() => profile.AddOrUpdateAsync(plugin.InternalName, enabled))
.ContinueWith(this.installer.DisplayErrorContinuation, Locs.ErrorCouldNotChangeState);
}
@ -411,9 +413,8 @@ internal class ProfileManagerWidget
if (wantRemovePluginInternalName != null)
{
// TODO: handle error
profile.Remove(wantRemovePluginInternalName, false);
Task.Run(() => profman.ApplyAllWantStates())
.ContinueWith(this.installer.DisplayErrorContinuation, Locs.ErrorCouldNotRemove);
Task.Run(() => profile.RemoveAsync(wantRemovePluginInternalName, false))
.ContinueWith(this.installer.DisplayErrorContinuation, Locs.ErrorCouldNotRemove);
}
if (!didAny)