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).
{
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*
// be acquired before attempting to acquire scriptlock, or else ServerThread
// will try to acquire scriptlock after it already owns envlock, thus
// deadlocking EmergeThread and ServerThread
- MutexAutoLock envlock(server->m_env_mutex);
SCRIPTAPI_PRECHECKHEADER
assert(state->script != NULL);
assert(state->refcount > 0);
+ // state must be protected by envlock
+ Server *server = state->script->getServer();
+ MutexAutoLock envlock(server->m_env_mutex);
+
state->refcount--;
state->script->on_emerge_area_completion(blockpos, action, state);