summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-01-19 12:52:41 +1100
committerjacqueline <me@jacqueline.id.au>2024-01-19 12:52:41 +1100
commitcd650b30bd3ddfb9f71622278ef5b6f94ae27ac8 (patch)
tree482058e274f0daee21a1e8798cdd39e4b94be17c /src
parent1525afe8aaadfaa877f8987f0ea224263a612b5e (diff)
downloadtangara-fw-cd650b30bd3ddfb9f71622278ef5b6f94ae27ac8.tar.gz
fix some lua stack leaks + add a console func to help debug
Diffstat (limited to 'src')
-rw-r--r--src/app_console/app_console.cpp21
-rw-r--r--src/lua/include/lua_thread.hpp2
-rw-r--r--src/lua/lua_thread.cpp58
-rw-r--r--src/lua/property.cpp4
-rw-r--r--src/ui/include/ui_events.hpp2
-rw-r--r--src/ui/include/ui_fsm.hpp2
-rw-r--r--src/ui/ui_fsm.cpp4
7 files changed, 93 insertions, 0 deletions
diff --git a/src/app_console/app_console.cpp b/src/app_console/app_console.cpp
index 2d16b60b..7347f130 100644
--- a/src/app_console/app_console.cpp
+++ b/src/app_console/app_console.cpp
@@ -43,6 +43,7 @@
#include "service_locator.hpp"
#include "system_events.hpp"
#include "track.hpp"
+#include "ui_events.hpp"
namespace console {
@@ -326,6 +327,25 @@ void RegisterHeaps() {
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
static heap_trace_record_t* sTraceRecords = nullptr;
static bool sIsTracking = false;
@@ -630,6 +650,7 @@ auto AppConsole::RegisterExtraComponents() -> void {
RegisterTasks();
RegisterHeaps();
+ RegisterStacks();
#if CONFIG_HEAP_TRACING
RegisterAllocs();
diff --git a/src/lua/include/lua_thread.hpp b/src/lua/include/lua_thread.hpp
index c85ccb91..d10dba3a 100644
--- a/src/lua/include/lua_thread.hpp
+++ b/src/lua/include/lua_thread.hpp
@@ -30,6 +30,8 @@ class LuaThread {
auto RunScript(const std::string& path) -> bool;
auto RunString(const std::string& path) -> bool;
+ auto DumpStack() -> void;
+
auto bridge() -> Bridge& { return *bridge_; }
auto state() -> lua_State* { return state_; }
diff --git a/src/lua/lua_thread.cpp b/src/lua/lua_thread.cpp
index dc588144..b94b70ab 100644
--- a/src/lua/lua_thread.cpp
+++ b/src/lua/lua_thread.cpp
@@ -6,8 +6,11 @@
#include "lua_thread.hpp"
+#include <iostream>
#include <memory>
+#include "lauxlib.h"
+#include "lua.h"
#include "lua.hpp"
#include "font/lv_font_loader.h"
@@ -123,6 +126,61 @@ auto LuaThread::RunString(const std::string& script) -> bool {
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) {
if (!lua_isstring(L, 1)) {
return 1;
diff --git a/src/lua/property.cpp b/src/lua/property.cpp
index 33600ee8..5357ccc5 100644
--- a/src/lua/property.cpp
+++ b/src/lua/property.cpp
@@ -113,6 +113,9 @@ PropertyBindings::PropertyBindings(lua_State& s) {
// Add our binding funcs (get, set, bind) to the metatable.
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.
lua_pushstring(&s, kBindingsTable);
lua_newtable(&s); // bindings = {}
@@ -368,6 +371,7 @@ auto Property::Update(const LuaValue& v) -> void {
PushValue(*b.first); // push the argument
CallProtected(b.first, 1, 0); // invoke the closure
+ lua_pop(b.first, 1); // pop the bindings table
}
}
diff --git a/src/ui/include/ui_events.hpp b/src/ui/include/ui_events.hpp
index 07b18dea..5c033b0c 100644
--- a/src/ui/include/ui_events.hpp
+++ b/src/ui/include/ui_events.hpp
@@ -28,6 +28,8 @@ struct OnLuaError : tinyfsm::Event {
std::string message;
};
+struct DumpLuaStack : tinyfsm::Event {};
+
namespace internal {
struct ControlSchemeChanged : tinyfsm::Event {};
diff --git a/src/ui/include/ui_fsm.hpp b/src/ui/include/ui_fsm.hpp
index 583a00a5..9de1169b 100644
--- a/src/ui/include/ui_fsm.hpp
+++ b/src/ui/include/ui_fsm.hpp
@@ -51,6 +51,7 @@ class UiState : public tinyfsm::Fsm<UiState> {
void react(const tinyfsm::Event& ev) {}
virtual void react(const OnLuaError&) {}
+ virtual void react(const DumpLuaStack&) {}
virtual void react(const internal::BackPressed&) {}
virtual void react(const system_fsm::BootComplete&) {}
virtual void react(const system_fsm::StorageMounted&) {}
@@ -148,6 +149,7 @@ class Lua : public UiState {
void exit() override;
void react(const OnLuaError&) override;
+ void react(const DumpLuaStack&) override;
void react(const internal::BackPressed&) override;
using UiState::react;
diff --git a/src/ui/ui_fsm.cpp b/src/ui/ui_fsm.cpp
index 7f94abc5..e532e693 100644
--- a/src/ui/ui_fsm.cpp
+++ b/src/ui/ui_fsm.cpp
@@ -541,6 +541,10 @@ void Lua::react(const OnLuaError& err) {
ESP_LOGE("lua", "%s", err.message.c_str());
}
+void Lua::react(const DumpLuaStack& ev) {
+ sLua->DumpStack();
+}
+
void Lua::react(const internal::BackPressed& ev) {
PopLuaScreen(sLua->state());
}