fix some lua stack leaks + add a console func to help debug

custom
jacqueline 1 year ago
parent 1525afe8aa
commit cd650b30bd
  1. 21
      src/app_console/app_console.cpp
  2. 2
      src/lua/include/lua_thread.hpp
  3. 58
      src/lua/lua_thread.cpp
  4. 4
      src/lua/property.cpp
  5. 2
      src/ui/include/ui_events.hpp
  6. 2
      src/ui/include/ui_fsm.hpp
  7. 4
      src/ui/ui_fsm.cpp

@ -43,6 +43,7 @@
#include "service_locator.hpp" #include "service_locator.hpp"
#include "system_events.hpp" #include "system_events.hpp"
#include "track.hpp" #include "track.hpp"
#include "ui_events.hpp"
namespace console { namespace console {
@ -326,6 +327,25 @@ void RegisterHeaps() {
esp_console_cmd_register(&cmd); esp_console_cmd_register(&cmd);
} }
int CmdStacks(int argc, char** argv) {
static const std::pmr::string usage = "usage: stacks";
if (argc != 1) {
std::cout << usage << std::endl;
return 1;
}
events::Ui().Dispatch(ui::DumpLuaStack{});
return 0;
}
void RegisterStacks() {
esp_console_cmd_t cmd{.command = "stacks",
.help = "prints contents of each lua stack",
.hint = NULL,
.func = &CmdStacks,
.argtable = NULL};
esp_console_cmd_register(&cmd);
}
#if CONFIG_HEAP_TRACING #if CONFIG_HEAP_TRACING
static heap_trace_record_t* sTraceRecords = nullptr; static heap_trace_record_t* sTraceRecords = nullptr;
static bool sIsTracking = false; static bool sIsTracking = false;
@ -630,6 +650,7 @@ auto AppConsole::RegisterExtraComponents() -> void {
RegisterTasks(); RegisterTasks();
RegisterHeaps(); RegisterHeaps();
RegisterStacks();
#if CONFIG_HEAP_TRACING #if CONFIG_HEAP_TRACING
RegisterAllocs(); RegisterAllocs();

@ -30,6 +30,8 @@ class LuaThread {
auto RunScript(const std::string& path) -> bool; auto RunScript(const std::string& path) -> bool;
auto RunString(const std::string& path) -> bool; auto RunString(const std::string& path) -> bool;
auto DumpStack() -> void;
auto bridge() -> Bridge& { return *bridge_; } auto bridge() -> Bridge& { return *bridge_; }
auto state() -> lua_State* { return state_; } auto state() -> lua_State* { return state_; }

@ -6,8 +6,11 @@
#include "lua_thread.hpp" #include "lua_thread.hpp"
#include <iostream>
#include <memory> #include <memory>
#include "lauxlib.h"
#include "lua.h"
#include "lua.hpp" #include "lua.hpp"
#include "font/lv_font_loader.h" #include "font/lv_font_loader.h"
@ -123,6 +126,61 @@ auto LuaThread::RunString(const std::string& script) -> bool {
return true; return true;
} }
auto LuaThread::DumpStack() -> void {
int top = lua_gettop(state_);
std::cout << "stack size: " << top << std::endl;
for (size_t i = 1; i <= top; i++) {
std::cout << "[" << i << "]\t" << luaL_typename(state_, i);
switch (lua_type(state_, i)) {
case LUA_TNUMBER:
std::cout << "\t(";
if (lua_isinteger(state_, i)) {
std::cout << lua_tointeger(state_, i);
} else {
std::cout << lua_tonumber(state_, i);
}
std::cout << ")";
break;
case LUA_TSTRING:
std::cout << "\t('" << lua_tostring(state_, i) << "')";
break;
case LUA_TBOOLEAN:
std::cout << "\t(" << lua_toboolean(state_, i) << ")";
break;
case LUA_TNIL:
// Value is implied.
break;
case LUA_TTABLE:
lua_pushnil(state_);
while (lua_next(state_, i) != 0) {
// Keys
std::cout << std::endl << "\t\t" << luaL_typename(state_, -2);
if (lua_type(state_, -2) == LUA_TSTRING) {
std::cout << "\t(" << lua_tostring(state_, -2) << ")";
} else if (lua_type(state_, -2) == LUA_TNUMBER) {
std::cout << "\t(" << lua_tonumber(state_, -2) << ")";
}
// Values
std::cout << "\t\t" << luaL_typename(state_, -1);
if (lua_type(state_, -1) == LUA_TSTRING) {
std::cout << "\t(" << lua_tostring(state_, -1) << ")";
} else if (lua_type(state_, -1) == LUA_TNUMBER) {
std::cout << "\t(" << lua_tonumber(state_, -1) << ")";
}
// Pop the value; we don't care about it. Leave the key on the stack
// for the next call to lua_next.
lua_pop(state_, 1);
}
break;
default:
std::cout << "\t(" << lua_topointer(state_, i) << ")";
break;
}
std::cout << std::endl;
}
}
static int msg_handler(lua_State* L) { static int msg_handler(lua_State* L) {
if (!lua_isstring(L, 1)) { if (!lua_isstring(L, 1)) {
return 1; return 1;

@ -113,6 +113,9 @@ PropertyBindings::PropertyBindings(lua_State& s) {
// Add our binding funcs (get, set, bind) to the metatable. // Add our binding funcs (get, set, bind) to the metatable.
luaL_setfuncs(&s, kPropertyBindingFuncs, 0); luaL_setfuncs(&s, kPropertyBindingFuncs, 0);
// We've finished setting up the metatable, so pop it.
lua_pop(&s, 1);
// Create a weak table in the registry to hold live bindings. // Create a weak table in the registry to hold live bindings.
lua_pushstring(&s, kBindingsTable); lua_pushstring(&s, kBindingsTable);
lua_newtable(&s); // bindings = {} lua_newtable(&s); // bindings = {}
@ -368,6 +371,7 @@ auto Property::Update(const LuaValue& v) -> void {
PushValue(*b.first); // push the argument PushValue(*b.first); // push the argument
CallProtected(b.first, 1, 0); // invoke the closure CallProtected(b.first, 1, 0); // invoke the closure
lua_pop(b.first, 1); // pop the bindings table
} }
} }

@ -28,6 +28,8 @@ struct OnLuaError : tinyfsm::Event {
std::string message; std::string message;
}; };
struct DumpLuaStack : tinyfsm::Event {};
namespace internal { namespace internal {
struct ControlSchemeChanged : tinyfsm::Event {}; struct ControlSchemeChanged : tinyfsm::Event {};

@ -51,6 +51,7 @@ class UiState : public tinyfsm::Fsm<UiState> {
void react(const tinyfsm::Event& ev) {} void react(const tinyfsm::Event& ev) {}
virtual void react(const OnLuaError&) {} virtual void react(const OnLuaError&) {}
virtual void react(const DumpLuaStack&) {}
virtual void react(const internal::BackPressed&) {} virtual void react(const internal::BackPressed&) {}
virtual void react(const system_fsm::BootComplete&) {} virtual void react(const system_fsm::BootComplete&) {}
virtual void react(const system_fsm::StorageMounted&) {} virtual void react(const system_fsm::StorageMounted&) {}
@ -148,6 +149,7 @@ class Lua : public UiState {
void exit() override; void exit() override;
void react(const OnLuaError&) override; void react(const OnLuaError&) override;
void react(const DumpLuaStack&) override;
void react(const internal::BackPressed&) override; void react(const internal::BackPressed&) override;
using UiState::react; using UiState::react;

@ -541,6 +541,10 @@ void Lua::react(const OnLuaError& err) {
ESP_LOGE("lua", "%s", err.message.c_str()); ESP_LOGE("lua", "%s", err.message.c_str());
} }
void Lua::react(const DumpLuaStack& ev) {
sLua->DumpStack();
}
void Lua::react(const internal::BackPressed& ev) { void Lua::react(const internal::BackPressed& ev) {
PopLuaScreen(sLua->state()); PopLuaScreen(sLua->state());
} }

Loading…
Cancel
Save