aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRogier <rogier777@gmail.com>2016-07-25 18:39:29 +0200
committerparamat <mat.gregory@virginmedia.com>2016-10-16 01:13:16 +0100
commit4b17105dc45976e399dab68f85b3030fa27f0ae2 (patch)
treee4df3345d4c8af05427754db97ea6e66031088df /src
parentadad6e0a1c2bb6cd5e56db26d660fa9342cf0d0e (diff)
downloadminetest-4b17105dc45976e399dab68f85b3030fa27f0ae2.tar.gz
minetest-4b17105dc45976e399dab68f85b3030fa27f0ae2.tar.bz2
minetest-4b17105dc45976e399dab68f85b3030fa27f0ae2.zip
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).
Diffstat (limited to 'src')
-rw-r--r--src/script/cpp_api/s_env.cpp4
-rw-r--r--src/script/lua_api/l_env.cpp4
2 files changed, 7 insertions, 1 deletions
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);