goatcorp / Dalamud

FFXIV plugin framework and API
GNU Affero General Public License v3.0
1.14k stars 270 forks source link

Allow plugins to be disposed when failing to load #1247

Open karashiiro opened 1 year ago

karashiiro commented 1 year ago

Sometimes, plugins have preconditions which should prevent them from loading, and the only way to force a load failure is to throw an exception. This does not dispose the plugin, and forces Dalamud/the game to be restarted in order to load the plugin again. Depending on where in the plugin initialization this happens, this leaves resources behind. Ideally, a plugin could have some way to signal that it should be disposed and enable reloading it even if it fails to load, to avoid this.

References:

KazWolfe commented 1 year ago

I'm not sure we can actually call Dispose() on a plugin that failed to load, as I don't necessarily think the object would even exist. We could (???) have some kind of static dispose, but that'd still need to do a lot of guessing (and have a lot of boilerplate) to intelligently clean things up.

However, this seems like it could be solved (at least in part) by #1202 and family. If we provide a service for the common explosion points (e.g. hooks), we'd be able to control the lifecycle of those things. If a plugin were to fail to load (throw an exception in the constructor), we'd record said failure and clean up all services.

As an example, let's say a plugin uses IHookService to create a few hooks into game code, and then subsequently fails to load. When cleaning up, IHookService will consult an internal list of all created hooks and dispose each of them, leaving the game in a much cleaner state.