mirror of
https://github.com/ArduPilot/ardupilot.git
synced 2026-02-08 12:12:36 +08:00
AP_Scripting: Add support for REPL over MAVLink
This commit is contained in:
committed by
WickedShell
parent
296c014d14
commit
cf06beb1e6
@@ -33,9 +33,10 @@ extern const AP_HAL::HAL& hal;
|
||||
bool lua_scripts::overtime;
|
||||
jmp_buf lua_scripts::panic_jmp;
|
||||
|
||||
lua_scripts::lua_scripts(const AP_Int32 &vm_steps, const AP_Int32 &heap_size, const AP_Int8 &debug_level)
|
||||
lua_scripts::lua_scripts(const AP_Int32 &vm_steps, const AP_Int32 &heap_size, const AP_Int8 &debug_level, struct AP_Scripting::terminal_s &_terminal)
|
||||
: _vm_steps(vm_steps),
|
||||
_debug_level(debug_level) {
|
||||
_debug_level(debug_level),
|
||||
terminal(_terminal) {
|
||||
_heap = hal.util->allocate_heap_memory(heap_size);
|
||||
}
|
||||
|
||||
@@ -52,6 +53,7 @@ void lua_scripts::hook(lua_State *L, lua_Debug *ar) {
|
||||
int lua_scripts::atpanic(lua_State *L) {
|
||||
gcs().send_text(MAV_SEVERITY_CRITICAL, "Lua: Panic: %s", lua_tostring(L, -1));
|
||||
hal.console->printf("Lua: Panic: %s\n", lua_tostring(L, -1));
|
||||
printf("Lua: Panic: %s\n", lua_tostring(L, -1));
|
||||
longjmp(panic_jmp, 1);
|
||||
return 0;
|
||||
}
|
||||
@@ -91,8 +93,16 @@ lua_scripts::script_info *lua_scripts::load_script(lua_State *L, char *filename)
|
||||
new_script->name = filename;
|
||||
new_script->next = nullptr;
|
||||
|
||||
create_sandbox(L);
|
||||
lua_setupvalue(L, -2, 1);
|
||||
|
||||
// find and create a sandbox for the new chunk
|
||||
new_script->lua_ref = luaL_ref(L, LUA_REGISTRYINDEX); // cache the reference
|
||||
new_script->next_run_ms = AP_HAL::millis64() - 1; // force the script to be stale
|
||||
|
||||
return new_script;
|
||||
}
|
||||
|
||||
void lua_scripts::create_sandbox(lua_State *L) {
|
||||
lua_newtable(L);
|
||||
luaopen_base_sandbox(L);
|
||||
lua_pushstring(L, "math");
|
||||
@@ -112,12 +122,7 @@ lua_scripts::script_info *lua_scripts::load_script(lua_State *L, char *filename)
|
||||
lua_settable(L, -3);
|
||||
load_lua_bindings(L);
|
||||
load_generated_sandbox(L);
|
||||
lua_setupvalue(L, -2, 1);
|
||||
|
||||
new_script->lua_ref = luaL_ref(L, LUA_REGISTRYINDEX); // cache the reference
|
||||
new_script->next_run_ms = AP_HAL::millis64() - 1; // force the script to be stale
|
||||
|
||||
return new_script;
|
||||
}
|
||||
|
||||
void lua_scripts::load_all_scripts_in_dir(lua_State *L, const char *dirname) {
|
||||
@@ -164,6 +169,13 @@ void lua_scripts::load_all_scripts_in_dir(lua_State *L, const char *dirname) {
|
||||
AP::FS().closedir(d);
|
||||
}
|
||||
|
||||
void lua_scripts::reset_loop_overtime(lua_State *L) {
|
||||
overtime = false;
|
||||
// reset the hook to clear the counter
|
||||
const int32_t vm_steps = MAX(_vm_steps, 1000);
|
||||
lua_sethook(L, hook, LUA_MASKCOUNT, vm_steps);
|
||||
}
|
||||
|
||||
void lua_scripts::run_next_script(lua_State *L) {
|
||||
if (scripts == nullptr) {
|
||||
#if defined(AP_SCRIPTING_CHECKS) && AP_SCRIPTING_CHECKS >= 1
|
||||
@@ -172,16 +184,12 @@ void lua_scripts::run_next_script(lua_State *L) {
|
||||
return;
|
||||
}
|
||||
|
||||
// reset the current script tracking information
|
||||
overtime = false;
|
||||
|
||||
// strip the selected script out of the list
|
||||
script_info *script = scripts;
|
||||
scripts = script->next;
|
||||
|
||||
// reset the hook to clear the counter
|
||||
const int32_t vm_steps = MAX(_vm_steps, 1000);
|
||||
lua_sethook(L, hook, LUA_MASKCOUNT, vm_steps);
|
||||
reset_loop_overtime(L);
|
||||
|
||||
// store top of stack so we can calculate the number of return values
|
||||
int stack_top = lua_gettop(L);
|
||||
@@ -192,7 +200,7 @@ void lua_scripts::run_next_script(lua_State *L) {
|
||||
if(lua_pcall(L, 0, LUA_MULTRET, 0)) {
|
||||
if (overtime) {
|
||||
// script has consumed an excessive amount of CPU time
|
||||
gcs().send_text(MAV_SEVERITY_CRITICAL, "Lua: %s exceeded time limit (%d)", script->name, (int)vm_steps);
|
||||
gcs().send_text(MAV_SEVERITY_CRITICAL, "Lua: %s exceeded time limit", script->name);
|
||||
remove_script(L, script);
|
||||
} else {
|
||||
hal.console->printf("Lua: Error: %s\n", lua_tostring(L, -1));
|
||||
@@ -314,6 +322,19 @@ void *lua_scripts::alloc(void *ud, void *ptr, size_t osize, size_t nsize) {
|
||||
return hal.util->heap_realloc(_heap, ptr, nsize);
|
||||
}
|
||||
|
||||
void lua_scripts::repl_cleanup (void) {
|
||||
if (terminal.session) {
|
||||
terminal.session = false;
|
||||
if (terminal.output_fd != -1) {
|
||||
AP::FS().close(terminal.output_fd);
|
||||
terminal.output_fd = -1;
|
||||
AP::FS().unlink(REPL_DIRECTORY "/in");
|
||||
AP::FS().unlink(REPL_DIRECTORY "/out");
|
||||
AP::FS().unlink(REPL_DIRECTORY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lua_scripts::run(void) {
|
||||
bool succeeded_initial_load = false;
|
||||
|
||||
@@ -336,6 +357,8 @@ void lua_scripts::run(void) {
|
||||
}
|
||||
scripts = nullptr;
|
||||
overtime = false;
|
||||
// end any open REPL sessions
|
||||
repl_cleanup();
|
||||
}
|
||||
|
||||
lua_state = lua_newstate(alloc, NULL);
|
||||
@@ -355,6 +378,12 @@ void lua_scripts::run(void) {
|
||||
succeeded_initial_load = true;
|
||||
|
||||
while (AP_Scripting::get_singleton()->enabled()) {
|
||||
// handle terminal data if we have any
|
||||
if (terminal.session) {
|
||||
doREPL(L);
|
||||
continue;
|
||||
}
|
||||
|
||||
#if defined(AP_SCRIPTING_CHECKS) && AP_SCRIPTING_CHECKS >= 1
|
||||
if (lua_gettop(L) != 0) {
|
||||
AP_HAL::panic("Lua: Stack should be empty before running scripts");
|
||||
|
||||
Reference in New Issue
Block a user