Skip to content

Keeping the server DLL handle alive fixes BugfixedAPI / WeaponMod conflict on Linux #310

Description

@isdpteam

Keeping the server DLL handle alive fixes BugfixedAPI / WeaponMod conflict on Linux

Environment

  • OS: Linux
  • Game: Half-Life Deathmatch
  • BugfixedHL-Rebased: 1.13.2+HEAD.3270cea
  • AMX Mod X: 1.10.0.5479
  • WeaponMod: v0.1.0-dev.323+HEAD.ec67f02
  • BugfixedAPI AMXX module: v1.13.2+HEAD.3270cea
  • WeaponMod repository: https://github.com/tmp64/weaponmod

Problem

When bugfixedapi_amxx_i386.so is loaded together with WeaponMod on Linux, custom WeaponMod weapons become partially broken after a map change.

Example with a custom SporeLauncher:

  • custom weapon registration works;
  • HUD weapon selection works;
  • custom PrimaryAttack logic works;
  • custom projectiles/effects work;
  • dropped weapon has the correct custom world model;
  • but after selecting the weapon, the first-person model becomes v_crowbar.mdl.

In one test the correct SporeLauncher view model was visible for a brief moment immediately after selection, then it was replaced by the crowbar model.

This is relevant because WeaponMod uses weapon_crowbar as the reference weapon and hooks its virtual functions.

Reproduction with original BugfixedAPI

  1. Start HLDS with WeaponMod v0.1.0-dev.323+HEAD.ec67f02 and BugfixedAPI v1.13.2+HEAD.3270cea.
  2. Obtain/select a custom WeaponMod weapon such as SporeLauncher.
  3. On the initial map it may work correctly.
  4. Change map.
  5. Select the custom weapon again.

Result:

Custom weapon mechanics: OK
Custom weapon firing:     OK
Custom world model:       OK
First-person model:       WRONG (crowbar)

The issue was reproduced even with almost all third-party AMXX plugins disabled.

If bugfixedapi_amxx_i386.so is physically removed and the server is fully restarted, WeaponMod works correctly. Multiple subsequent map changes also work correctly.

If BugfixedAPI has already been loaded into the process and the broken state has occurred, unloading BugfixedAPI does not necessarily restore WeaponMod; a full server restart is required.

Suspicious code

In:

src/bugfixedapi_amxx/bhl_api.cpp

InitServerApi() currently does:

g_pServerModule = Sys_LoadModule(pszModule);

if (!g_pServerModule)
    return E_ApiInitResult::ModuleNotFound;

// Decrease reference count - module should still be loaded by the engine
Sys_UnloadModule(g_pServerModule);

// Get factory
g_fnServerFactory = Sys_GetFactory(g_pServerModule);

On Linux Sys_UnloadModule() calls dlclose().

So the effective sequence is:

dlopen(server DLL)
dlclose(server DLL)
dlsym/use the same handle afterwards

Although the server DLL is also loaded by the engine and normally remains resident, this lifetime pattern appears to interact badly with WeaponMod's runtime virtual hooks.

Test patch

For testing, I modified BugfixedAPI so that the extra server DLL reference is kept alive for the whole lifetime of the AMXX module.

The immediate Sys_UnloadModule(g_pServerModule) call was removed from InitServerApi().

The reference is instead released in ShutdownServerApi():

void bhl::ShutdownServerApi()
{
    g_pServerApi = nullptr;
    g_iServerMajor = 0;
    g_iServerMinor = 0;
    g_fnServerFactory = nullptr;

    if (g_pServerModule)
    {
        Sys_UnloadModule(g_pServerModule);
        g_pServerModule = nullptr;
    }
}

Failure paths after a successful Sys_LoadModule() were also adjusted to release the handle before returning.

No WeaponMod, AMXX, gamedata, offsets or GameDLL changes were made.

Test result

The modified module reports:

BugfixedAPI v1.13.2+HEAD.3270cea.m

Test 1 — BugfixedAPI auto-loaded later

[ 5] HL Weapon Mod   RUN   weaponmod_amxx_i386.so
     v0.1.0-dev.323+HEAD.ec67f02

[11] BugfixedAPI     RUN   bugfixedapi_amxx_i386.so
     v1.13.2+HEAD.3270cea.m

Multiple map changes: OK.

Custom weapon view models continue to work correctly.

Test 2 — BugfixedAPI explicitly loaded immediately after WeaponMod

modules.ini:

weaponmod
bugfixedapi

Result:

[ 5] HL Weapon Mod   RUN   weaponmod_amxx_i386.so
     v0.1.0-dev.323+HEAD.ec67f02

[ 6] BugfixedAPI     RUN   bugfixedapi_amxx_i386.so
     v1.13.2+HEAD.3270cea.m

Again, multiple map changes: OK.

The original bug could no longer be reproduced.

Expected behavior

Loading BugfixedAPI should not affect WeaponMod virtual hooks or custom weapon view models across map changes.

Actual behavior with the original module

After BugfixedAPI has been loaded, WeaponMod custom weapons can lose their custom first-person model after a map change and fall back to the reference weapon_crowbar model.

Conclusion

Keeping the Sys_LoadModule() reference alive until ShutdownServerApi() completely eliminates the issue in my tests, regardless of whether BugfixedAPI is loaded early from modules.ini or auto-loaded later by AMXX.

This strongly suggests that the current immediate Sys_UnloadModule() in InitServerApi() is involved in the conflict.

I can provide the exact patch or compiled test module if needed.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions