CounterStrikeSharp icon indicating copy to clipboard operation
CounterStrikeSharp copied to clipboard

Unloading and loading a plugin does not re-load types

Open milesizzo opened this issue 1 month ago • 1 comments

Unloading and loading a plugin does not re-load the types (and thus does not re-initialise any static members). This side-effect can leave a plugin in an invalid state on load.

To demonstrate the issue:

public class CanaryPlugin : BasePlugin
{
    public override string ModuleName => "CanaryPlugin";

    public override string ModuleVersion => "1.0.0";

    private static bool isStaticInitialised = false;

    public override void Load(bool hotReload)
    {
        if (isStaticInitialised)
        {
            this.Logger.LogWarning("{CanaryPlugin} type is already initialized", nameof(CanaryPlugin));
        }
        this.Logger.LogInformation("CanaryPlugin loaded (hotReload: {HotReload})", hotReload);
        isStaticInitialised = true;
    }

    public override void Unload(bool hotReload)
    {
        this.Logger.LogInformation("CanaryPlugin unloaded (hotReload: {HotReload})", hotReload);
    }
}

Execute these commands:

css_plugins load CanaryPlugin
css_plugins unload CanaryPlugin
css_plugins load CanaryPlugin

Output:

01:37:17 [INFO] (cssharp:PluginContext) Loading plugin CanaryPlugin
01:37:17 [INFO] (plugin:CanaryPlugin) CanaryPlugin loaded (hotReload: False)
01:37:17 [INFO] (cssharp:PluginContext) Finished loading plugin CanaryPlugin
01:37:24 [INFO] (cssharp:PluginContext) Unloading plugin CanaryPlugin
01:37:24 [INFO] (plugin:CanaryPlugin) CanaryPlugin unloaded (hotReload: False)
01:37:24 [INFO] (cssharp:PluginContext) Finished unloading plugin CanaryPlugin
01:37:29 [INFO] (cssharp:PluginContext) Loading plugin CanaryPlugin
01:37:29 [WARN] (plugin:CanaryPlugin) CanaryPlugin type is already initialized
01:37:29 [INFO] (plugin:CanaryPlugin) CanaryPlugin loaded (hotReload: False)
01:37:29 [INFO] (cssharp:PluginContext) Finished loading plugin CanaryPlugin

The solution might be to dispose the underlying PluginLoader when a plugin is unloaded. If this behaviour is intentional I think it should be documented prominently.

milesizzo avatar Oct 27 '25 01:10 milesizzo

similar to #565

KillStr3aK avatar Oct 28 '25 05:10 KillStr3aK