From 52e5b513ed9dc143c967c733423fe751e1b663d1 Mon Sep 17 00:00:00 2001 From: kwolekr Date: Sat, 31 Oct 2015 16:31:43 -0400 Subject: Fix Lua scripting synchronization For several years now, the lua script lock has been completely broken. This commit fixes the main issue (creation of a temporary rather than scoped object), and fixes a subsequent deadlock issue caused by nested script API calls by adding support for recursive mutexes. --- src/script/cpp_api/s_internal.h | 42 +++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) (limited to 'src/script/cpp_api/s_internal.h') diff --git a/src/script/cpp_api/s_internal.h b/src/script/cpp_api/s_internal.h index 7daf8c03f..651fed95f 100644 --- a/src/script/cpp_api/s_internal.h +++ b/src/script/cpp_api/s_internal.h @@ -32,28 +32,50 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifdef SCRIPTAPI_LOCK_DEBUG #include "debug.h" // assert() + class LockChecker { public: - LockChecker(bool *variable) { - assert(*variable == false); + LockChecker(int *recursion_counter, threadid_t *owning_thread) + { + m_lock_recursion_counter = recursion_counter; + m_owning_thread = owning_thread; + m_original_level = *recursion_counter; + + if (*m_lock_recursion_counter > 0) + assert(thr_is_current_thread(*m_owning_thread)); + else + *m_owning_thread = thr_get_current_thread_id(); - m_variable = variable; - *m_variable = true; + (*m_lock_recursion_counter)++; } - ~LockChecker() { - *m_variable = false; + + ~LockChecker() + { + assert(thr_is_current_thread(*m_owning_thread)); + assert(*m_lock_recursion_counter > 0); + + (*m_lock_recursion_counter)--; + + assert(*m_lock_recursion_counter == m_original_level); } + private: - bool *m_variable; + int *m_lock_recursion_counter; + int m_original_level; + threadid_t *m_owning_thread; }; -#define SCRIPTAPI_LOCK_CHECK LockChecker(&(this->m_locked)) +#define SCRIPTAPI_LOCK_CHECK \ + LockChecker scriptlock_checker( \ + &this->m_lock_recursion_count, \ + &this->m_owning_thread) + #else -#define SCRIPTAPI_LOCK_CHECK while(0) + #define SCRIPTAPI_LOCK_CHECK while(0) #endif #define SCRIPTAPI_PRECHECKHEADER \ - MutexAutoLock(this->m_luastackmutex); \ + MutexAutoLock scriptlock(this->m_luastackmutex); \ SCRIPTAPI_LOCK_CHECK; \ realityCheck(); \ lua_State *L = getStack(); \ -- cgit v1.2.3