}
}
+static void LuaThread(const std::string code)
+{
+ LuaContext l;
+ // submitToMainThread is camelcased, threadmessage is not.
+ // This follows our tradition of hooks we call being lowercased but functions the user can call being camelcased.
+ l.writeFunction("submitToMainThread", [](std::string cmd, std::unordered_map<std::string, std::string> data) {
+ auto lua = g_lua.lock();
+ // maybe offer more than `void`
+ auto func = lua->readVariable<boost::optional<std::function<void(std::string cmd, std::unordered_map<std::string, std::string> data)>>>("threadmessage");
+ if (func) {
+ func.get()(cmd, data);
+ }
+ else {
+ errlog("Lua thread called submitToMainThread but no threadmessage receiver is defined");
+ }
+ });
+
+ // function threadmessage(cmd, data) print("got thread data:", cmd) for k,v in pairs(data) do print(k,v) end end
+
+ for (;;) {
+ try {
+ l.executeCode(code);
+ errlog("Lua thread exited, restarting in 5 seconds");
+ }
+ catch (const std::exception& e) {
+ errlog("Lua thread crashed, restarting in 5 seconds: %s", e.what());
+ }
+ catch (...) {
+ errlog("Lua thread crashed, restarting in 5 seconds");
+ }
+ sleep(5);
+ }
+}
+
static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
{
typedef std::unordered_map<std::string, boost::variant<bool, std::string, vector<pair<int, std::string>>, DownstreamState::checkfunc_t>> newserver_t;
}
});
#endif /* HAVE_LIBSSL */
+
+ luaCtx.writeFunction("newThread", [](const std::string& code) {
+ std::thread newThread(LuaThread, code);
+ newThread.detach();
+ });
}
vector<std::function<void(void)>> setupLua(LuaContext& luaCtx, bool client, bool configCheck, const std::string& config)
--- /dev/null
+#!/usr/bin/env python
+
+import base64
+import time
+import unittest
+from dnsdisttests import DNSDistTest
+
+class TestLuaThread(DNSDistTest):
+ _consoleKey = DNSDistTest.generateConsoleKey()
+ _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii')
+
+ _config_params = ['_consoleKeyB64', '_consolePort']
+ _config_template = """
+ setKey("%s")
+ controlSocket("127.0.0.1:%s")
+
+ counter = 0
+ function threadmessage(cmd, data)
+ print("counter says", cmd, data.i)
+ counter = tonumber(data.i)
+ end
+
+ newThread([==[
+ local socket = require'socket'
+ local i=1
+ while true
+ do
+ socket.sleep(1)
+ submitToMainThread("setCounter", {i=i})
+ i = i + 1
+ end
+ ]==])
+ """
+
+ def testLuaThreadCounter(self):
+ """
+ LuaThread: Test the lua newThread interface
+ """
+ count1 = self.sendConsoleCommand('counter')
+ time.sleep(3)
+ count2 = self.sendConsoleCommand('counter')
+ self.assertTrue(count2 > count1)