Emergeblocks: Fix occasional crash

Modification of the emergeblocks internal state was not protected
by a lock, causing a race condition.
This can be reproduced by repeatedly running emergeblocks for an
already-generated section of the map (with multiple emerge threads).
This commit is contained in:
Rogier 2016-07-25 18:39:29 +02:00 committed by paramat
parent adad6e0a1c
commit 4b17105dc4
2 changed files with 7 additions and 1 deletions

@ -212,11 +212,13 @@ void ScriptApiEnv::on_emerge_area_completion(
{ {
Server *server = getServer(); Server *server = getServer();
// This function should be executed with envlock held.
// The caller (LuaEmergeAreaCallback in src/script/lua_api/l_env.cpp)
// should have obtained the lock.
// Note that the order of these locks is important! Envlock must *ALWAYS* // Note that the order of these locks is important! Envlock must *ALWAYS*
// be acquired before attempting to acquire scriptlock, or else ServerThread // be acquired before attempting to acquire scriptlock, or else ServerThread
// will try to acquire scriptlock after it already owns envlock, thus // will try to acquire scriptlock after it already owns envlock, thus
// deadlocking EmergeThread and ServerThread // deadlocking EmergeThread and ServerThread
MutexAutoLock envlock(server->m_env_mutex);
SCRIPTAPI_PRECHECKHEADER SCRIPTAPI_PRECHECKHEADER

@ -137,6 +137,10 @@ void LuaEmergeAreaCallback(v3s16 blockpos, EmergeAction action, void *param)
assert(state->script != NULL); assert(state->script != NULL);
assert(state->refcount > 0); assert(state->refcount > 0);
// state must be protected by envlock
Server *server = state->script->getServer();
MutexAutoLock envlock(server->m_env_mutex);
state->refcount--; state->refcount--;
state->script->on_emerge_area_completion(blockpos, action, state); state->script->on_emerge_area_completion(blockpos, action, state);