(fixed) Crash on delayed teleport and invalid id

This forum is for the Lua scriptable clone of DM/CSB called Dungeon Strikes Back by Sophia. Use DSB to build your own highly customised games.

Moderator: Sophia

Forum rules
Please read the Forum rules and policies before posting.
Post Reply
kaypy
Artisan
Posts: 171
Joined: Sun Jan 19, 2014 7:11 am

(fixed) Crash on delayed teleport and invalid id

Post by kaypy »

Hi

Under some circumstances, it is possible for teleports and messages to combine to crash the system. The teleport can get delayed indefinitely, and if the target is deleted for any reason then everything falls over due to messages involving a now-invalid id...

simple test case:
http://en.file-upload.net/download-1077 ... h.zip.html

fix:
add a test for validity to triggers.lua/finish_queued_teleport:

Code: Select all

function finish_queued_teleport(id)
	local targ = exvar[id].inst
	local lev = exvar[id].lev
	local xc = exvar[id].x
	local yc = exvar[id].y
	
	if (exvar[id].disabled) then return end
-- test added here:
	if (not dsb_valid_inst(targ)) then return end
	
	local occupied = nil
	...
Friends don't let friends eat worm round
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Crash on delayed teleport and invalid id

Post by Sophia »

Thanks.

The actual fix is more complicated to prevent it from leaking object instances... but I think somehow I missed this the first time around and the default code does that anyway. So I'll fix both of these bugs for DSB 0.66.

In the meantime, you can replace finish_queued_teleport with this version:

Code: Select all

function finish_queued_teleport(id)
	local targ = exvar[id].inst
	local lev = exvar[id].lev
	local xc = exvar[id].x
	local yc = exvar[id].y
	
	if (exvar[id].disabled) then return end
	
	-- Target is gone, give up!
	if (not dsb_valid_inst(targ)) then
		dsb_msg(1, id, M_DESTROY, 0)
		return
	end
	local tlev = dsb_get_coords(targ)
	if (tlev ~= LIMBO) then
		dsb_msg(1, id, M_DESTROY, 0)
		return
	end
	
	local occupied = nil
	if (exvar[id].tries < 1500) then
		occupied = teleport_needs_queue(targ, lev, xc, yc, nil)
		exvar[id].tries = exvar[id].tries + 1
	end
	
	if (occupied) then
		dsb_msg(2, id, M_ACTIVATE, 0)
	else	
		local pos = CENTER
		if (exvar[targ] and exvar[targ].teleport_tile_pos) then
			pos = exvar[targ].teleport_tile_pos
			exvar[targ].teleport_tile_pos = nil
		end
		
		dsb_move(targ, lev, xc, yc, pos)
		
		local action_time = dsb_ai(targ, AI_TIMER, QUERY)
		if (action_time < 3) then
			dsb_ai(targ, AI_TIMER, 3)
		end
		
		local arch = dsb_find_arch(targ)
		if (arch.on_teleport) then
			arch:on_teleport(targ, lev, xc, yc, pos)
		end
		
		dsb_msg(1, id, M_DESTROY, 0)
	end
end
Post Reply