From 4b17105dc45976e399dab68f85b3030fa27f0ae2 Mon Sep 17 00:00:00 2001
From: Rogier <rogier777@gmail.com>
Date: Mon, 25 Jul 2016 18:39:29 +0200
Subject: [PATCH] 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).
---
 src/script/cpp_api/s_env.cpp | 4 +++-
 src/script/lua_api/l_env.cpp | 4 ++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/script/cpp_api/s_env.cpp b/src/script/cpp_api/s_env.cpp
index 82d0d4f0e..913d8539d 100644
--- a/src/script/cpp_api/s_env.cpp
+++ b/src/script/cpp_api/s_env.cpp
@@ -212,11 +212,13 @@ void ScriptApiEnv::on_emerge_area_completion(
 {
 	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
 
diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp
index f6ea23e95..68d10308c 100644
--- a/src/script/lua_api/l_env.cpp
+++ b/src/script/lua_api/l_env.cpp
@@ -137,6 +137,10 @@ void LuaEmergeAreaCallback(v3s16 blockpos, EmergeAction action, void *param)
 	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);
-- 
GitLab