Add ignore_world_load_errors configuration option and provide better error messages

This commit is contained in:
Perttu Ahola 2012-06-04 22:34:22 +03:00
parent 1cd2076d42
commit f48882213e
5 changed files with 62 additions and 12 deletions

@ -178,4 +178,7 @@
# To reduce lag, block transfers are slowed down when a player is building something. # To reduce lag, block transfers are slowed down when a player is building something.
# This determines how long they are slowed down after placing or removing a node. # This determines how long they are slowed down after placing or removing a node.
#full_block_send_enable_min_time_from_building = 2.0 #full_block_send_enable_min_time_from_building = 2.0
# Length of a server tick in dedicated server
#dedicated_server_step = 0.05
# Can be set to true to disable shutting down on invalid world data
#ignore_world_load_errors = false

@ -137,5 +137,6 @@ void set_default_settings(Settings *settings)
settings->setDefault("server_map_save_interval", "5.3"); settings->setDefault("server_map_save_interval", "5.3");
settings->setDefault("full_block_send_enable_min_time_from_building", "2.0"); settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");
settings->setDefault("dedicated_server_step", "0.05"); settings->setDefault("dedicated_server_step", "0.05");
settings->setDefault("ignore_world_load_errors", "false");
} }

@ -3378,14 +3378,20 @@ void ServerMap::loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool
} }
catch(SerializationError &e) catch(SerializationError &e)
{ {
infostream<<"WARNING: Invalid block data in database " errorstream<<"Invalid block data in database"
<<" (SerializationError). " <<" ("<<p3d.X<<","<<p3d.Y<<","<<p3d.Z<<")"
<<"what()="<<e.what() <<" (SerializationError): "<<e.what()<<std::endl;
<<std::endl;
//" Ignoring. A new one will be generated. // TODO: Block should be marked as invalid in memory so that it is
assert(0); // not touched but the game can run
// TODO: Copy to a backup database. if(g_settings->getBool("ignore_world_load_errors")){
errorstream<<"Ignoring block load error. Duck and cover! "
<<"(ignore_world_load_errors)"<<std::endl;
} else {
throw SerializationError("Invalid block data in database");
//assert(0);
}
} }
} }

@ -35,6 +35,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapblock_mesh.h" #include "mapblock_mesh.h"
#endif #endif
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
/* /*
MapBlock MapBlock
*/ */
@ -634,6 +636,8 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
{ {
if(!ser_ver_supported(version)) if(!ser_ver_supported(version))
throw VersionMismatchException("ERROR: MapBlock format not supported"); throw VersionMismatchException("ERROR: MapBlock format not supported");
TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())<<std::endl);
m_day_night_differs_expired = false; m_day_night_differs_expired = false;
@ -652,6 +656,8 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
/* /*
Bulk node data Bulk node data
*/ */
TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
<<": Bulk node data"<<std::endl);
u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
u8 content_width = readU8(is); u8 content_width = readU8(is);
u8 params_width = readU8(is); u8 params_width = readU8(is);
@ -665,6 +671,8 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
/* /*
NodeMetadata NodeMetadata
*/ */
TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
<<": Node metadata"<<std::endl);
// Ignore errors // Ignore errors
try{ try{
std::ostringstream oss(std::ios_base::binary); std::ostringstream oss(std::ios_base::binary);
@ -680,7 +688,8 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
catch(SerializationError &e) catch(SerializationError &e)
{ {
errorstream<<"WARNING: MapBlock::deSerialize(): Ignoring an error" errorstream<<"WARNING: MapBlock::deSerialize(): Ignoring an error"
<<" while deserializing node metadata: "<<e.what()<<std::endl; <<" while deserializing node metadata at ("
<<PP(getPos())<<": "<<e.what()<<std::endl;
} }
/* /*
@ -689,21 +698,33 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
if(disk) if(disk)
{ {
// Node timers // Node timers
if(version >= 23) if(version >= 23){
TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
<<": Node timers"<<std::endl);
m_node_timers.deSerialize(is); m_node_timers.deSerialize(is);
}
// Static objects // Static objects
TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
<<": Static objects"<<std::endl);
m_static_objects.deSerialize(is); m_static_objects.deSerialize(is);
// Timestamp // Timestamp
TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
<<": Timestamp"<<std::endl);
setTimestamp(readU32(is)); setTimestamp(readU32(is));
m_disk_timestamp = m_timestamp; m_disk_timestamp = m_timestamp;
// Dynamically re-set ids based on node names // Dynamically re-set ids based on node names
TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
<<": NameIdMapping"<<std::endl);
NameIdMapping nimap; NameIdMapping nimap;
nimap.deSerialize(is); nimap.deSerialize(is);
correctBlockNodeIds(&nimap, data, m_gamedef); correctBlockNodeIds(&nimap, data, m_gamedef);
} }
TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
<<": Done."<<std::endl);
} }
/* /*

@ -164,6 +164,8 @@ void * EmergeThread::Thread()
BEGIN_DEBUG_EXCEPTION_HANDLER BEGIN_DEBUG_EXCEPTION_HANDLER
bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info"); bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info");
v3s16 last_tried_pos(-32768,-32768,-32768); // For error output
/* /*
Get block info from queue, emerge them and send them Get block info from queue, emerge them and send them
@ -181,6 +183,8 @@ void * EmergeThread::Thread()
v3s16 &p = q->pos; v3s16 &p = q->pos;
v2s16 p2d(p.X,p.Z); v2s16 p2d(p.X,p.Z);
last_tried_pos = p;
/* /*
Do not generate over-limit Do not generate over-limit
@ -377,8 +381,23 @@ void * EmergeThread::Thread()
} }
catch(VersionMismatchException &e) catch(VersionMismatchException &e)
{ {
m_server->setAsyncFatalError(std::string( std::ostringstream err;
"World data version mismatch (server-side) (world probably saved by a newer version of Minetest): ")+e.what()); err<<"World data version mismatch in MapBlock "<<PP(last_tried_pos)<<std::endl;
err<<"----"<<std::endl;
err<<"\""<<e.what()<<"\""<<std::endl;
err<<"See debug.txt."<<std::endl;
err<<"World probably saved by a newer version of Minetest."<<std::endl;
m_server->setAsyncFatalError(err.str());
}
catch(SerializationError &e)
{
std::ostringstream err;
err<<"Invalid data in MapBlock "<<PP(last_tried_pos)<<std::endl;
err<<"----"<<std::endl;
err<<"\""<<e.what()<<"\""<<std::endl;
err<<"See debug.txt."<<std::endl;
err<<"You can ignore this using [ignore_world_load_errors = true]."<<std::endl;
m_server->setAsyncFatalError(err.str());
} }
END_DEBUG_EXCEPTION_HANDLER(errorstream) END_DEBUG_EXCEPTION_HANDLER(errorstream)