Enable interrupting pure Lua loops

This commit is contained in:
redfast00 2021-09-16 18:16:30 +02:00
parent ec7290984e
commit f5501273e2
No known key found for this signature in database
GPG key ID: 5946E0E34FD0553C
6 changed files with 46 additions and 9 deletions

1
.gitignore vendored
View file

@ -1,4 +1,5 @@
.build/ .build/
build/
editor/.idea/ editor/.idea/
editor/.cache editor/.cache
editor/dist editor/dist

View file

@ -5,7 +5,6 @@ function all_leds(red, green, blue)
end end
while true do while true do
print(ledamount())
all_leds(255, 128, 0) all_leds(255, 128, 0)
delay(1000) delay(1000)
all_leds(0, 128, 255) all_leds(0, 128, 255)

2
demo/2.lua Normal file
View file

@ -0,0 +1,2 @@
print("script begin")
while true do end

View file

@ -1,3 +1,4 @@
#!/bin/bash #!/bin/bash
scp -r main root@10.1.0.212:ledstrip_sandbox/ scp -r main root@10.1.0.212:ledstrip_sandbox/
ssh root@10.1.0.212 "cd ledstrip_sandbox/ && cmake --build build"

View file

@ -17,6 +17,9 @@
#include "httplib.h" #include "httplib.h"
using json = nlohmann::json; using json = nlohmann::json;
using std::chrono::duration_cast;
using std::chrono::milliseconds;
using std::chrono::system_clock;
#define TARGET_FREQ WS2811_TARGET_FREQ #define TARGET_FREQ WS2811_TARGET_FREQ
@ -62,9 +65,28 @@ ws2811_t ledstring =
}, },
}, },
}; };
void hook(lua_State* L, lua_Debug *ar);
inline bool kill_thread_if_desired(lua_State *L) {
if (!statemap[L]->enabled)
{
cout << "putting errors on the stack" << endl;
lua_sethook(L, hook, LUA_MASKLINE, 0);
luaL_error(L, "killed by manager");
return true;
}
return false;
}
// TODO also call this hook about once every second
void hook(lua_State* L, lua_Debug *ar)
{
kill_thread_if_desired(L);
}
extern "C" { extern "C" {
static int c_override_print (lua_State *L) { static int c_override_print (lua_State *L) {
kill_thread_if_desired(L);
int n = lua_gettop(L); /* number of arguments */ int n = lua_gettop(L); /* number of arguments */
int i; int i;
for (i = 1; i <= n; i++) { /* for each argument */ for (i = 1; i <= n; i++) { /* for each argument */
@ -80,6 +102,7 @@ extern "C" {
} }
static int c_led (lua_State *L) { static int c_led (lua_State *L) {
kill_thread_if_desired(L);
int virtual_location = luaL_checkinteger(L, 1); int virtual_location = luaL_checkinteger(L, 1);
int red = luaL_checkinteger(L, 2); int red = luaL_checkinteger(L, 2);
int green = luaL_checkinteger(L, 3); int green = luaL_checkinteger(L, 3);
@ -115,17 +138,27 @@ extern "C" {
} }
static int c_ledamount(lua_State *L) { static int c_ledamount(lua_State *L) {
kill_thread_if_desired(L);
lua_pushinteger(L, statemap[L]->length); lua_pushinteger(L, statemap[L]->length);
return 1; return 1;
} }
static int c_delay(lua_State *L) { static int c_delay(lua_State *L) {
int millis = luaL_checkinteger (L, 1); if (kill_thread_if_desired(L)) {return 0;}
std::this_thread::sleep_for(std::chrono::milliseconds(millis)); uint64_t millis = luaL_checkinteger (L, 1);
uint64_t begin = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
while (duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count() - begin < millis - 100) {
std::this_thread::sleep_for(std::chrono::milliseconds(100-5));
if (kill_thread_if_desired(L)) {return 0;}
}
uint64_t passed = (duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count() - begin);
std::this_thread::sleep_for(std::chrono::milliseconds(millis-passed));
return 0; return 0;
} }
static int c_waitframes(lua_State *L) { static int c_waitframes(lua_State *L) {
kill_thread_if_desired(L);
int amount = luaL_checkinteger(L, 1); int amount = luaL_checkinteger(L, 1);
uint64_t destination = amount + framecounter; uint64_t destination = amount + framecounter;
if (amount >= 2 * FPS) { if (amount >= 2 * FPS) {
@ -186,6 +219,8 @@ lua_State* setup_lua_sandbox(const char* luacode) {
lua_setglobal(L, "print"); lua_setglobal(L, "print");
luaL_loadbuffer(L, luacode, strlen(luacode), "script"); luaL_loadbuffer(L, luacode, strlen(luacode), "script");
lua_sethook(L, hook, LUA_MASKCOUNT, 1000);
return L; return L;
} }
@ -258,7 +293,6 @@ int main(int argc, char** argv)
}); });
svr.Put("/api/code.json", [](const httplib::Request &req, httplib::Response &res, const httplib::ContentReader &content_reader) { svr.Put("/api/code.json", [](const httplib::Request &req, httplib::Response &res, const httplib::ContentReader &content_reader) {
cout << "put request" << endl;
if (req.is_multipart_form_data()) { if (req.is_multipart_form_data()) {
res.set_content("No multipart forms allowed", "text/plain"); res.set_content("No multipart forms allowed", "text/plain");
return true; return true;
@ -266,15 +300,16 @@ int main(int argc, char** argv)
content_reader([&](const char *raw_data, size_t data_length) { content_reader([&](const char *raw_data, size_t data_length) {
std::string data(raw_data, data_length); std::string data(raw_data, data_length);
auto j = json::parse(data); auto j = json::parse(data);
cout << j << endl;
LedSegment* selected = ledsegments.at(j["id"].get<unsigned int>()); LedSegment* selected = ledsegments.at(j["id"].get<unsigned int>());
if (selected->lua_thread.has_value()) { if (selected->lua_thread.has_value()) {
// TODO kill lua thread selected->interpreter_config->enabled = false;
selected->lua_thread.value().join();
} }
selected->owner = j["owner"].get<std::string>(); selected->owner = j["owner"].get<std::string>();
selected->lua_code = j["code"].get<std::string>(); selected->lua_code = j["code"].get<std::string>();
selected->interpreter_config->enabled = true;
selected->lua_thread = spawn_lua_tread(selected->lua_code.c_str(), selected->interpreter_config); selected->lua_thread = spawn_lua_tread(selected->lua_code.c_str(), selected->interpreter_config);
cout << "Uploaded new code from " << selected->owner << " to segment " << j["id"].get<unsigned int>() << endl;
return true; return true;
}); });
} }

View file

@ -13,7 +13,6 @@ for i in range(10):
c = codefile.read() c = codefile.read()
except: except:
continue continue
time.sleep(0.3)
j = { j = {
"code": c, "code": c,
"owner": "j", "owner": "j",