sourcemod icon indicating copy to clipboard operation
sourcemod copied to clipboard

Load plugins marked as dependencies before their dependents

Open nosoop opened this issue 3 years ago • 4 comments

Fixes the root issue of nosoop/SM-TFEconDataCompat#4 (comment), among others.

Given a plugin that depends on a shared plugin that depends on an extension native, the dependent plugin is initialized before the shared plugin. The dependent plugin may call into the shared plugin at OnPluginStart, which will fail since the natives the shared plugin depends on aren't bound.

This patch forces the second loading pass on the plugin's dependencies before its own second loading pass completes.

Compiled and tested this patch on my test TF2 instance with no known side effects.

nosoop avatar Feb 05 '22 16:02 nosoop

Appears to have been previously discussed on the old AM bug tracker.

OnAllPluginsLoaded doesn't really help in this case because the plugin in question is also a shared plugin:

  • TF2 Taunts TF2IDB expects the Econ Data compatibility shim (acting as TF2IDB) to have its database initialized during its OnAllPluginsLoaded
  • the Econ Data compatibility shim can't initialize its database ~~before OnAllPluginsLoaded~~ at its OnPluginStart since it depends on Econ Data being loaded in (since it depends on being able to call SDKCall)

It does look like handling the database initialization during OnLibraryAdded works for this particular case, so I can have the compatibility shim depend on that instead.

However, without this or a similar fix, I'm almost certain that if TF2 Taunts TF2IDB ran its own code during OnLibraryAdded, this issue would remain since it would be running before the Econ Data compatibility shim's OnLibraryAdded.

nosoop avatar Feb 06 '22 14:02 nosoop

It sounds like a broken API on this one - the reason why is there's no forward or similar to indicate the parent API is ready. Blocking or demanding a full load before the library is ready feels strange. This is similar to Steam_OnLoaded / OnClientCookiesCached / etc.

KyleSanderson avatar Feb 09 '22 01:02 KyleSanderson

It sounds like a broken API on this one - the reason why is there's no forward or similar to indicate the parent API is ready. Blocking or demanding a full load before the library is ready feels strange. This is similar to Steam_OnLoaded / OnClientCookiesCached / etc.

Those forwards make sense for asynchronous / indeterminate operations, sure. As far as I'm aware, everything here is synchronous; I believe this is strictly an ordering issue.

The intent of the PR is to effectively reorder the iteration here so that (non-circular) dependencies consistently perform their second pass of loading before any of their dependents:

https://github.com/alliedmodders/sourcemod/blob/8f73e5e5a1947c1e7d3525cd7771e5546d2aa84b/core/logic/PluginSys.cpp#L1063-L1073

As it is, I can already try to manipulate the load order by having a particular directory structure.

nosoop avatar Feb 09 '22 16:02 nosoop

Please don't do this - there is no reason to have ordering dependencies between plugins. Loading is already way too complex.

dvander avatar Feb 10 '22 05:02 dvander

From the input above, this doesn't sound like a sustainable change. If changing the plugin loading at all it should be simplified, since any issues with it are already hard to debug. The plugin loading order is an implementation detail and shouldn't be relied on.

Even if there is no asynchronous part in your example, the preferred solution would be to add a OnReady forward and fire it in a RequestFrame callback on the next frame.

peace-maker avatar Dec 02 '22 13:12 peace-maker