From f2a5f525261e2dc73c04bc81ec4f4bc513d78e78 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Wed, 8 Mar 2023 04:09:22 +1100 Subject: [PATCH] Lua: Be more strict with concurrency and multiple contexts. --- plugins/console/init.lua | 10 +++++----- src/frontend/mame/luaengine.cpp | 35 ++++++++++++++++++++++----------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/plugins/console/init.lua b/plugins/console/init.lua index 33f698fc0cb..f9e712a66a9 100644 --- a/plugins/console/init.lua +++ b/plugins/console/init.lua @@ -45,8 +45,8 @@ function console.startplugin() function(c, str) status = str yield() - for k, v in pairs(status) do - ln.addcompletion(c, v) + for candidate in status:gmatch('([^\001]+)') do + ln.addcompletion(c, candidate) end end) local ret = ln.linenoise('$PROMPT') @@ -207,9 +207,9 @@ function console.startplugin() local str, strs, expr, sep = simplify_expression(line, word) contextual_list(expr, sep, str, word, strs) if #matches == 0 then - return { line } + return line elseif #matches == 1 then - return { start .. matches[1] } + return start .. matches[1] end print("") result = { } @@ -217,7 +217,7 @@ function console.startplugin() print(v) table.insert(result, start .. v) end - return result + return table.concat(result, '\001') end emu.register_start(function() diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp index 04b68b75e9a..063f01dc5c9 100644 --- a/src/frontend/mame/luaengine.cpp +++ b/src/frontend/mame/luaengine.cpp @@ -63,7 +63,7 @@ namespace { struct thread_context { private: - sol::object m_result; + std::string m_result; std::mutex m_guard; std::condition_variable m_sync; @@ -73,7 +73,7 @@ public: bool start(char const *scr) { - std::unique_lock lock(m_guard); + std::unique_lock caller_lock(m_guard); if (m_busy) return false; @@ -87,6 +87,7 @@ public: thstate["package"]["preload"]["lfs"] = &luaopen_lfs; thstate["package"]["preload"]["linenoise"] = &luaopen_linenoise; sol::load_result res = thstate.load(script); + std::unique_lock result_lock(m_guard, std::defer_lock); if (res.valid()) { sol::protected_function func = res.get(); @@ -94,17 +95,24 @@ public: "yield", [this, &thstate]() { - std::unique_lock lock(m_guard); + std::unique_lock yield_lock(m_guard); m_result = thstate["status"]; m_yield = true; - m_sync.wait(lock); + m_sync.wait(yield_lock); m_yield = false; thstate["status"] = m_result; }); auto ret = func(); + result_lock.lock(); if (ret.valid()) { - m_result = ret.get(); + auto result = ret.get >(); + if (!result) + osd_printf_error("[LUA ERROR] in thread: return value must be string\n"); + else if (!*result) + m_result.clear(); + else + m_result = *result; } else { @@ -114,10 +122,12 @@ public: } else { + result_lock.lock(); sol::error err = res; osd_printf_error("[LUA ERROR] when loading script for thread: %s\n", err.what()); } - m_busy = false; // FIXME: shouldn't do this when not holding the lock + assert(result_lock); + m_busy = false; }); m_busy = true; m_yield = false; @@ -125,23 +135,26 @@ public: return true; } - void resume(sol::object val) + void resume(char const *val) { std::unique_lock lock(m_guard); if (m_yield) { - m_result = val; + if (val) + m_result = val; + else + m_result.clear(); m_sync.notify_all(); } } - sol::object result() + char const *result() { std::unique_lock lock(m_guard); if (m_busy && !m_yield) - return sol::lua_nil; + return ""; else - return m_result; + return m_result.c_str(); } };