summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2023-03-08 04:09:22 +1100
committer Vas Crabb <vas@vastheman.com>2023-03-08 04:09:22 +1100
commitf2a5f525261e2dc73c04bc81ec4f4bc513d78e78 (patch)
tree657a66441fa7142a37f532f8149afc18dd2ac8f7
parent6dea565343e81ab6b8c6da880ba166ba28235da8 (diff)
Lua: Be more strict with concurrency and multiple contexts.
-rw-r--r--plugins/console/init.lua10
-rw-r--r--src/frontend/mame/luaengine.cpp35
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<std::mutex> lock(m_guard);
+ std::unique_lock<std::mutex> 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<std::mutex> result_lock(m_guard, std::defer_lock);
if (res.valid())
{
sol::protected_function func = res.get<sol::protected_function>();
@@ -94,17 +95,24 @@ public:
"yield",
[this, &thstate]()
{
- std::unique_lock<std::mutex> lock(m_guard);
+ std::unique_lock<std::mutex> 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<sol::object>();
+ auto result = ret.get<std::optional<char const *> >();
+ 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<std::mutex> 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<std::mutex> lock(m_guard);
if (m_busy && !m_yield)
- return sol::lua_nil;
+ return "";
else
- return m_result;
+ return m_result.c_str();
}
};