Hello All,
I’ve been working on a game with Urho3D using the Lua bindings. Recently I added some lua code that removes nodes whose “health” value has hit 0. This crashed the engine (as in segfault) in some other lua code which had stored the node in a table. I would expect the entries to be either nil’d out or have some sort of “invalid” marker that could be checked, but I haven’t discovered anything that might work like that. It appears from the C++ code that the node is being deleted (when node:Remove() is called) even though Lua still has pointers to it (hence the segfault later on). Could this be fixed by using sharedptrs for lua references? If not, how can I store nodes in a table safely?
Here’s a short standalone script illustrating the problem (you can run it with Urho3DPlayer in headless mode):
local total = 0
local lastPrintTime = 0
local invalidNodes = {}
function Start()
scene_ = Scene()
-- Create scene subsystem components
scene_:CreateComponent("Octree", LOCAL)
local phys = scene_:CreateComponent("PhysicsWorld", LOCAL)
phys.gravity = Vector3(0,-9.8,0)
SubscribeToEvent("Update", "UpdateStuff")
end
LifeTimer = ScriptObject()
function UpdateStuff()
local dt = 0.02
-- Make sure there are 10 alive objects
while total < 10 do
print("Creating")
local newNode = scene_:CreateChild()
newNode:CreateScriptObject("LifeTimer")
total = total + 1
print("Created")
end
-- Print out the table every so often
lastPrintTime = lastPrintTime + dt
if lastPrintTime > 1 then
for i,n in ipairs(invalidNodes) do
-- Problems occur on the next two lines
print(">>>>> Test:",n.ID,n.position.x)
n:SendEvent("Junk")
end
print("Done test")
lastPrintTime = lastPrintTime-1
end
end
function LifeTimer:Start()
self.life = 1.5
self.node.position = Vector3(Random(-10,10),Random(-10,10),Random(-10,10))
print("Start")
end
function LifeTimer:Stop()
print("Stop")
end
function LifeTimer:FixedUpdate(dt)
self.life = self.life - dt
if self.life <= 0 then
print("Removing")
-- Add to table before removing
table.insert(invalidNodes, self.node)
-- Remove the node
self.node:Remove()
print("Removed")
total = total - 1
end
end
It might not crash for a while (or it might give Lua errors instead), but Valgrind will show you the problems.
I’m using the git master branch on 64-bit Linux.