From f42b01c74bdc7e91d3def03125a0e24e6a3bb0d4 Mon Sep 17 00:00:00 2001 From: orwell96 Date: Wed, 5 Apr 2017 13:57:09 +0200 Subject: Add pcall wrapper to prevent server crashes when advtrains throws an error Instead, read save files again and restore state before the crash Rebased to latest commit --- advtrains.zip | Bin 4991936 -> 4992304 bytes advtrains/advtrains/atc.lua | 6 +++++ advtrains/advtrains/couple.lua | 17 +++++++++++++- advtrains/advtrains/init.lua | 30 ++++++++++++++++++++++++ advtrains/advtrains/nodedb.lua | 6 +++++ advtrains/advtrains/trackplacer.lua | 8 +++++++ advtrains/advtrains/trainlogic.lua | 9 +++++++ advtrains/advtrains/wagons.lua | 15 ++++++++++++ advtrains/advtrains_luaautomation/interrupt.lua | 3 +++ 9 files changed, 93 insertions(+), 1 deletion(-) diff --git a/advtrains.zip b/advtrains.zip index 02ab8b1..eb47749 100644 Binary files a/advtrains.zip and b/advtrains.zip differ diff --git a/advtrains/advtrains/atc.lua b/advtrains/advtrains/atc.lua index 3925ffd..577f858 100644 --- a/advtrains/advtrains/atc.lua +++ b/advtrains/advtrains/atc.lua @@ -92,12 +92,17 @@ advtrains.register_tracks("default", { return { after_place_node=apn_func, after_dig_node=function(pos) + return advtrains.pcall(function() + advtrains.invalidate_all_paths() advtrains.ndb.clear(pos) local pts=minetest.pos_to_string(pos) atc.controllers[pts]=nil + end) end, on_receive_fields = function(pos, formname, fields, player) + return advtrains.pcall(function() + if advtrains.is_protected(pos, player:get_player_name()) then minetest.record_protection_violation(pos, player:get_player_name()) return @@ -135,6 +140,7 @@ advtrains.register_tracks("default", { atc.send_command(pos) end end + end) end, advtrains = { on_train_enter = function(pos, train_id) diff --git a/advtrains/advtrains/couple.lua b/advtrains/advtrains/couple.lua index eb1bc72..3693e84 100644 --- a/advtrains/advtrains/couple.lua +++ b/advtrains/advtrains/couple.lua @@ -31,6 +31,8 @@ minetest.register_entity("advtrains:discouple", { end, get_staticdata=function() return "DISCOUPLE" end, on_punch=function(self, player) + return advtrains.pcall(function() + --only if player owns at least one wagon next to this local own=player:get_player_name() if self.wagon.owner and self.wagon.owner==own and not self.wagon.lock_couples then @@ -54,8 +56,11 @@ minetest.register_entity("advtrains:discouple", { else minetest.chat_send_player(own, attrans("You need to own at least one neighboring wagon to destroy this couple.")) end + end) end, on_step=function(self, dtime) + return advtrains.pcall(function() + local t=os.clock() if not self.wagon then self.object:remove() @@ -77,6 +82,7 @@ minetest.register_entity("advtrains:discouple", { self.updatepct_timer=2 end atprintbm("discouple_step", t) + end) end, }) @@ -98,16 +104,21 @@ minetest.register_entity("advtrains:couple", { initial_sprite_basepos = {x=0, y=0}, is_couple=true, - on_activate=function(self, staticdata) + on_activate=function(self, staticdata) + return advtrains.pcall(function() + if staticdata=="COUPLE" then --couple entities have no right to exist further... atprint("Couple loaded from staticdata, destroying") self.object:remove() return end + end) end, get_staticdata=function(self) return "COUPLE" end, on_rightclick=function(self, clicker) + return advtrains.pcall(function() + if not self.train_id_1 or not self.train_id_2 then return end local id1, id2=self.train_id_1, self.train_id_2 @@ -128,8 +139,11 @@ minetest.register_entity("advtrains:couple", { end atprint("Coupled trains", id1, id2) self.object:remove() + end) end, on_step=function(self, dtime) + return advtrains.pcall(function() + local t=os.clock() if not self.train_id_1 or not self.train_id_2 then atprint("Couple: train ids not set!") self.object:remove() return end local train1=advtrains.trains[self.train_id_1] @@ -167,5 +181,6 @@ minetest.register_entity("advtrains:couple", { end end atprintbm("couple step", t) + end) end, }) diff --git a/advtrains/advtrains/init.lua b/advtrains/advtrains/init.lua index 970bbb6..9b7f31f 100644 --- a/advtrains/advtrains/init.lua +++ b/advtrains/advtrains/init.lua @@ -9,6 +9,29 @@ end advtrains = {trains={}, wagon_save={}, player_to_train_mapping={}} +--pcall +local no_action=true +function advtrains.pcall(fun) + if no_action then return end + + local succ, err, return1, return2, return3, return4=pcall(fun) + if not succ then + atwarn("Lua Error occured: ", err) + atwarn("Restoring saved state in 1 second...") + no_action=true + --read last save state and continue, as if server was restarted + for aoi, le in pairs(minetest.luaentities) do + if le.is_wagon then + le.object:remove() + end + end + minetest.after(1, advtrains.load) + else + return err, return1, return2, return3, return4 + end +end + + advtrains.modpath = minetest.get_modpath("advtrains") function advtrains.print_concat_table(a) @@ -94,6 +117,9 @@ dofile(advtrains.modpath.."/craft_items.lua") --load/save advtrains.fpath=minetest.get_worldpath().."/advtrains" + +function advtrains.load() + local file, err = io.open(advtrains.fpath, "r") if not file then minetest.log("error", " Failed to read advtrains save data from file "..advtrains.fpath..": "..(err or "Unknown Error")) @@ -142,6 +168,10 @@ else end file:close() end +no_action=false + +end +advtrains.load() advtrains.save = function() --atprint("saving") diff --git a/advtrains/advtrains/nodedb.lua b/advtrains/advtrains/nodedb.lua index ddd1a67..2fb3656 100644 --- a/advtrains/advtrains/nodedb.lua +++ b/advtrains/advtrains/nodedb.lua @@ -203,6 +203,8 @@ minetest.register_abm({ nodenames = {"group:save_in_nodedb"}, run_at_every_load = true, action = function(pos, node) + return advtrains.pcall(function() + local cid=ndbget(pos.x, pos.y, pos.z) if cid then --if in database, detect changes and apply. @@ -227,14 +229,18 @@ minetest.register_abm({ atprint("nodedb: ", pos, "not in database") ndb.update(pos, node) end + end) end, interval=10, chance=1, }) minetest.register_on_dignode(function(pos, oldnode, digger) +return advtrains.pcall(function() + ndb.clear(pos) end) +end) function ndb.get_nodes() return ndb_nodes diff --git a/advtrains/advtrains/trackplacer.lua b/advtrains/advtrains/trackplacer.lua index e039800..5f9bdf7 100644 --- a/advtrains/advtrains/trackplacer.lua +++ b/advtrains/advtrains/trackplacer.lua @@ -187,6 +187,8 @@ function tp.register_track_placer(nnprefix, imgprefix, dispname) wield_image = imgprefix.."_placer.png", groups={}, on_place = function(itemstack, placer, pointed_thing) + return advtrains.pcall(function() + local name = placer:get_player_name() if not name then return itemstack @@ -207,6 +209,7 @@ function tp.register_track_placer(nnprefix, imgprefix, dispname) end end return itemstack + end) end, }) end @@ -220,6 +223,7 @@ minetest.register_craftitem("advtrains:trackworker",{ wield_image = "advtrains_trackworker.png", stack_max = 1, on_place = function(itemstack, placer, pointed_thing) + return advtrains.pcall(function() local name = placer:get_player_name() if not name then return @@ -260,8 +264,11 @@ minetest.register_craftitem("advtrains:trackworker",{ advtrains.ndb.swap_node(pos, {name=nnprefix.."_"..suffix..modext[modpos+1], param2=node.param2}) end end + end) end, on_use=function(itemstack, user, pointed_thing) + return advtrains.pcall(function() + local name = user:get_player_name() if not name then return @@ -292,6 +299,7 @@ minetest.register_craftitem("advtrains:trackworker",{ else atprint(name, dump(tp.tracks)) end + end) end, }) diff --git a/advtrains/advtrains/trainlogic.lua b/advtrains/advtrains/trainlogic.lua index d9edd6d..0caea0b 100644 --- a/advtrains/advtrains/trainlogic.lua +++ b/advtrains/advtrains/trainlogic.lua @@ -40,6 +40,8 @@ advtrains.save_interval=10 advtrains.save_timer=advtrains.save_interval minetest.register_globalstep(function(dtime_mt) +return advtrains.pcall(function() + --limit dtime: if trains move too far in one step, automation may cause stuck and wrongly braking trains local dtime=dtime_mt if dtime>0.2 then @@ -81,8 +83,11 @@ minetest.register_globalstep(function(dtime_mt) atprintbm("trainsteps", t) endstep() end) +end) minetest.register_on_joinplayer(function(player) +return advtrains.pcall(function() + local pname=player:get_player_name() local id=advtrains.player_to_train_mapping[pname] if id then @@ -101,8 +106,11 @@ minetest.register_on_joinplayer(function(player) end end end) +end) minetest.register_on_dieplayer(function(player) +return advtrains.pcall(function() + local pname=player:get_player_name() local id=advtrains.player_to_train_mapping[pname] if id then @@ -117,6 +125,7 @@ minetest.register_on_dieplayer(function(player) end end end) +end) --[[ train step structure: diff --git a/advtrains/advtrains/wagons.lua b/advtrains/advtrains/wagons.lua index 15a0ec7..2ceea86 100644 --- a/advtrains/advtrains/wagons.lua +++ b/advtrains/advtrains/wagons.lua @@ -50,6 +50,7 @@ function wagon:on_activate(sd_uid, dtime_s) end function wagon:get_staticdata() +return advtrains.pcall(function() if not self:ensure_init() then return end atprint("[wagon "..((self.unique_id and self.unique_id~="" and self.unique_id) or "no-id").."]: saving to wagon_save") --serialize inventory, if it has one @@ -63,6 +64,7 @@ function wagon:get_staticdata() advtrains.wagon_save[self.unique_id].name=nil advtrains.wagon_save[self.unique_id].object=nil return self.unique_id +end) end --returns: uid of wagon function wagon:init_new_instance(train_id, properties) @@ -147,6 +149,7 @@ end -- Remove the wagon function wagon:on_punch(puncher, time_from_last_punch, tool_capabilities, direction) +return advtrains.pcall(function() if not self:ensure_init() then return end if not puncher or not puncher:is_player() then return @@ -177,6 +180,7 @@ function wagon:on_punch(puncher, time_from_last_punch, tool_capabilities, direct inv:add_item("main", item) end end +end) end function wagon:destroy() --some rules: @@ -211,6 +215,8 @@ end function wagon:on_step(dtime) +return advtrains.pcall(function() + if not self:ensure_init() then return end local t=os.clock() @@ -465,6 +471,7 @@ function wagon:on_step(dtime) self.old_acceleration_vector=accelerationvec self.old_yaw=yaw atprintbm("wagon step", t) +end) end function advtrains.get_real_path_index(train, pit) @@ -485,6 +492,8 @@ function advtrains.get_real_path_index(train, pit) end function wagon:on_rightclick(clicker) +return advtrains.pcall(function() + if not self:ensure_init() then return end if not clicker or not clicker:is_player() then return @@ -564,6 +573,7 @@ function wagon:on_rightclick(clicker) self:show_get_on_form(pname) end end +end) end function wagon:get_on(clicker, seatno) @@ -708,6 +718,8 @@ function wagon:show_wagon_properties(pname) minetest.show_formspec(pname, "advtrains_prop_"..self.unique_id, form) end minetest.register_on_player_receive_fields(function(player, formname, fields) +return advtrains.pcall(function() + local uid=string.match(formname, "^advtrains_geton_(.+)$") if uid then for _,wagon in pairs(minetest.luaentities) do @@ -780,6 +792,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end end end) +end) function wagon:seating_from_key_helper(pname, fields, no) local sgr=self.seats[no].group for _,access in ipairs(self.seat_groups[sgr].access_to) do @@ -841,6 +854,7 @@ function advtrains.register_wagon(sysname, prototype, desc, inv_img) stack_max = 1, on_place = function(itemstack, placer, pointed_thing) + return advtrains.pcall(function() if not pointed_thing.type == "node" then return end @@ -876,6 +890,7 @@ function advtrains.register_wagon(sysname, prototype, desc, inv_img) end return itemstack + end) end, }) end diff --git a/advtrains/advtrains_luaautomation/interrupt.lua b/advtrains/advtrains_luaautomation/interrupt.lua index 4d59db5..b8fc879 100644 --- a/advtrains/advtrains_luaautomation/interrupt.lua +++ b/advtrains/advtrains_luaautomation/interrupt.lua @@ -22,6 +22,8 @@ function iq.add(t, pos, evtdata) end minetest.register_globalstep(function(dtime) +return advtrains.pcall(function() + if run then timer=timer + math.min(dtime, 0.2) for i=1,#queue do @@ -42,6 +44,7 @@ minetest.register_globalstep(function(dtime) end end end) +end) -- cgit v1.2.3