BeamMP / BeamMP-Server

Server for the multiplayer mod BeamMP for BeamNG.drive
https://beammp.com
GNU Affero General Public License v3.0
128 stars 53 forks source link

[Bug] Reloading plugin creates duplicate event timers #194

Open Dreae opened 10 months ago

Dreae commented 10 months ago

OS (windows, linux, ...): windows BeamMP-Server Version: master

Describe the bug Plugin auto-reloading on file changes does not clear timers created with CreateEventTimer causing duplicate timers to be created every time the plugin reloads. This also causes a crash if the event handler function changes name when the plugin reloads.

To Reproduce Steps to reproduce the behavior:

  1. Create a timer using CreateEventTimer
  2. Trigger a plugin reload by saving a file
  3. The event function will be called twice per-period due to duplicate event timers

Expected behavior Reloading plugins clears existing event timers so they will be recreated cleanly when the plugin restarts

Logs

[26/11/23 12:30:51] main.cpp:196 [INFO] ALL SYSTEMS STARTED SUCCESSFULLY, EVERYTHING IS OKAY
[26/11/23 12:30:52] LuaAPI.cpp:105 [LUA] Hello there    
[26/11/23 12:30:54] LuaAPI.cpp:105 [LUA] Hello there    
> status
BeamMP-Server Status:
    Total Players:             0
    Syncing Players:           0
    Synced Players:            0
    Connected Players:         0
    Guests:                    0
    Cars:                      0
    Uptime:                    10201ms (~0h) 
    Lua:
        Queued results to check:     0
        States:                      2
        Event timers:                1
        Event handlers:              1
    Subsystems:
        Good/Starting/Bad:           11/0/0
        Shutting down/Shut down:     0/0
        Good:                        [ Main, Server, Heartbeat, LuaEngine, Config, PPSMonitor, ResourceManager, UpdateCheck, PluginMonitor, TCPNetwork, UDPNetwork ]
        Starting:                    [  ]
        Bad:                         [  ]
        Shutting down:               [  ]
        Shut down:                   [  ]

[26/11/23 12:30:56] LuaAPI.cpp:105 [LUA] Hello there    
[26/11/23 12:30:58] LuaAPI.cpp:105 [LUA] Hello there    
[26/11/23 12:31:00] LuaAPI.cpp:105 [LUA] Hello there    
[26/11/23 12:31:01] TPluginMonitor.cpp:41 [INFO] File "Resources\Server\TimerTest\main.lua" changed, reloading
[26/11/23 12:31:02] LuaAPI.cpp:105 [LUA] Hello there    
[26/11/23 12:31:03] LuaAPI.cpp:105 [LUA] Hello there    
[26/11/23 12:31:04] LuaAPI.cpp:105 [LUA] Hello there    
[26/11/23 12:31:05] LuaAPI.cpp:105 [LUA] Hello there    
[26/11/23 12:31:06] LuaAPI.cpp:105 [LUA] Hello there    
[26/11/23 12:31:07] LuaAPI.cpp:105 [LUA] Hello there    
[26/11/23 12:31:07] TPluginMonitor.cpp:41 [INFO] File "Resources\Server\TimerTest\main.lua" changed, reloading
[26/11/23 12:31:08] LuaAPI.cpp:105 [LUA] Hello there    
[26/11/23 12:31:09] LuaAPI.cpp:105 [LUA] Hello there    
[26/11/23 12:31:09] LuaAPI.cpp:105 [LUA] Hello there    
[26/11/23 12:31:10] LuaAPI.cpp:105 [LUA] Hello there    
[26/11/23 12:31:11] LuaAPI.cpp:105 [LUA] Hello there    
[26/11/23 12:31:11] LuaAPI.cpp:105 [LUA] Hello there    
[26/11/23 12:31:12] LuaAPI.cpp:105 [LUA] Hello there    
> status
BeamMP-Server Status:
    Total Players:             0
    Syncing Players:           0
    Synced Players:            0
    Connected Players:         0
    Guests:                    0
    Cars:                      0
    Uptime:                    27491ms (~0h) 
    Lua:
        Queued results to check:     0
        States:                      2
        Event timers:                3
        Event handlers:              1
    Subsystems:
        Good/Starting/Bad:           11/0/0
        Shutting down/Shut down:     0/0
        Good:                        [ Main, Server, Heartbeat, LuaEngine, Config, PPSMonitor, ResourceManager, UpdateCheck, PluginMonitor, TCPNetwork, UDPNetwork ]
        Starting:                    [  ]
        Bad:                         [  ]
        Shutting down:               [  ]
        Shut down:                   [  ]

Additional Context Lua file used to reproduce the issue:

function SayHello()
    print("Hello there")
end

MP.RegisterEvent("TestTimer", "SayHello")
MP.CreateEventTimer("TestTimer", 2000)
lionkor commented 10 months ago

The way this currently is worked around is by always cancelling your event timers before starting them, much like unsubscribing event handlers in other languages before subscribing. Cancelling a nonexistent event timer is a no-op.

So, dirty fix:

  function SayHello()
      print("Hello there")
  end

  MP.RegisterEvent("TestTimer", "SayHello")
+ MP.CancelEventTimer("TestTimer")
  MP.CreateEventTimer("TestTimer", 2000)

Fixing this would require the following changes to be made to the lua/plugin engine:

You could also potentially add an event for onBeforeReload or something, but nobody would end up using that IMO.