mtasa-blue icon indicating copy to clipboard operation
mtasa-blue copied to clipboard

setElementModel - memory leaking

Open srslyyyy opened this issue 2 years ago • 7 comments

Describe the bug

Calling setElementModel would cause GTA process to claim memory and never free it. It happens for peds, didn't tested other types though.

Steps to reproduce

local playerSkins = {11, 9, 7}
local skinsCount = #playerSkins

function changeSkin()
    local randomSkin = math.random(1, skinsCount)
    local newSkin = playerSkins[randomSkin]

    setElementModel(localPlayer, newSkin)
end
setTimer(changeSkin, 1, 0)

Run this code and observe GTA process memory usage in task manager.

Version

Client/server: Multi Theft Auto v1.5.9-release-21261

Additional context

/

Relevant log output

No response

Security Policy

  • [X] I have read and understood the Security Policy and this issue is not security related.

srslyyyy avatar Jul 16 '22 21:07 srslyyyy

I can reproduce this. A few things to note:

  • Restarting the resource does not clean up the memory.
  • Making the loop stop does not clean up the memory.
  • Using /showmemstat shows that only the Process Memory is going up.
  • The problem only occurs with peds,players. Tried with vehicles and objects and it doesn't happen with them.
  • Having the ped streamed off does seem to make the leak stop (but that could be because the ped I tried was clientsided and their model was being changed clientside aswell).
  • Disconnecting from the server does not clean up the memory (also I crashed with Offset = 0x00349EE4 after re-joining).

PlatinMTA avatar Jul 17 '22 10:07 PlatinMTA

I did a little investigation on this and it seems somehow related to CAnimBlockSA - you can find the same by using VS 2022 memory profiling tools, creating various snapshots with & without the test script running and comparing object counts.

From a very quick glance at the code, suspicion is that we are losing reference to old CAnimBlockSA objects when a new model is applied to a ped, and therefore never destroying them when necessary?

Lpsd avatar Jul 17 '22 15:07 Lpsd

Seems like this produces the same results too

local peds = {}
local playerSkins = {11, 9, 7}
local skinsCount = #playerSkins

function spawnPeds()
    local randomSkin = math.random(1, skinsCount)
    local newSkin = playerSkins[randomSkin]
    local x, y, z = getElementPosition(localPlayer)

    peds[#peds+1] = createPed(newSkin, x + math.random(5), y + math.random(5), z + math.random())

    if (#peds > 5) then
        local oldPed = table.remove(peds, 1)
        destroyElement(oldPed)
    end
end
setTimer(spawnPeds, 1, 0)

setElementModel actually causes ped to be destroyed and created again. I tried this to confirm it's something to do with that process & CAnimBlockSA (as mentioned above) - memory profiling seems to suggest it's the same issue.

Lpsd avatar Jul 17 '22 16:07 Lpsd

Using setElementModel increases vehicle count in model cache section (showmemstat) up to it's cap and stays there forever. I'm not sure that it works as expected and it might be related to thia issue. I'm able to reproduce it on latest nightly build (client & server) using default admin panel resource with default SA vehicles.

JeViCo avatar Aug 02 '22 11:08 JeViCo

Alleged culprits: https://github.com/multitheftauto/mtasa-blue/blob/08cd7480da6a2d5b4f00f1978d7ddc8c915b3206/Client/mods/deathmatch/logic/CClientPed.cpp#L3930

https://github.com/multitheftauto/mtasa-blue/blob/08cd7480da6a2d5b4f00f1978d7ddc8c915b3206/Client/mods/deathmatch/logic/CClientPed.cpp#L3922

Dutchman101 — Today at 2:39 PM [issue link] We need someone with enough GTA internals knownledge for this, but there's not many

TEDERIs — Today at 3:09 PM This is an old well known leak. And it was intentially allowed by commenting out some of code lines in the MTA source(see NO_CRASH_FIX_TEST and NO_CRASH_FIX_TEST2 macro). It seems that releasing ped geometries led to crashes in the past. When I was working on fork, we had implemented a garbage collector for this situations. But of course this is only a half measure. We're not using GTA models at all now, but I will try to look into it later.

Dutchman101 — Today at 3:10 PM oh, and how about other models like vehicle?

TEDERIs — Today at 3:41 PM I think in case of vehicles we have a similar problem with references. It should be checked in first of all. But it's just an assumption.

Dutchman101 avatar Apr 12 '23 13:04 Dutchman101

The commented out code seems to suggest that it only happens when the model is changed from CJ to a non-CJ model or vice versa, no?

Pirulax avatar Aug 26 '23 18:08 Pirulax

The commented out code seems to suggest that it only happens when the model is changed from CJ to a non-CJ model or vice versa, no?

A simple check tells that this happens with all models. You can remove NO_CRASH_FIX_TEST directives and see that the leak no longer bothers(at least, the ref counting works as it should).

tederis avatar Aug 27 '23 01:08 tederis