[Tarantool-patches] [PATCH v3 3/4] fiber: refactor lua backtrace routines
eelchinov at tarantool.org
eelchinov at tarantool.org
Wed Jul 14 14:12:51 MSK 2021
From: Egor Elchinov <elchinov.es at gmail.com>
Lua backtrace with callback moved to new routine
`lua_backtrace_cb()` similar to the `backtrace_cb()`
for C backtrace.
Needed for: #4002
---
src/lua/fiber.c | 170 ++++++++++++++++++++++--------------------------
1 file changed, 76 insertions(+), 94 deletions(-)
diff --git a/src/lua/fiber.c b/src/lua/fiber.c
index fbf68c561..59d72fc52 100644
--- a/src/lua/fiber.c
+++ b/src/lua/fiber.c
@@ -205,14 +205,17 @@ struct lua_parent_tb_ctx {
int tb_frame;
};
+/** Lua backtrace callback type */
+typedef int (lua_backtrace_cb)(struct lua_Debug *ar, int frame_no, void *cb_ctx);
+
#ifdef ENABLE_BACKTRACE
static void
-dump_lua_frame(struct lua_State *L, lua_Debug *ar, int tb_frame)
+dump_lua_frame(struct lua_State *L, const char *name, const char *src, int line,
+ int tb_frame)
{
char buf[512];
snprintf(buf, sizeof(buf), "%s in %s at line %i",
- ar->name != NULL ? ar->name : "(unnamed)",
- ar->source, ar->currentline);
+ name != NULL ? name : "(unnamed)", src, line);
buf[sizeof(buf) - 1] = 0;
lua_pushnumber(L, tb_frame);
lua_newtable(L);
@@ -222,21 +225,67 @@ dump_lua_frame(struct lua_State *L, lua_Debug *ar, int tb_frame)
lua_settable(L, -3);
}
+static int
+dump_lua_frame_cb(lua_Debug *ar, int tb_frame, void *cb_ctx)
+{
+ (void) tb_frame;
+ struct lua_fiber_tb_ctx *tb_ctx = (struct lua_fiber_tb_ctx *)cb_ctx;
+
+ tb_ctx->tb_frame++;
+ dump_lua_frame(tb_ctx->L, ar->name, ar->source, ar->currentline,
+ tb_ctx->tb_frame);
+
+ return 0;
+}
+
+static int
+save_lua_frame_cb(lua_Debug *ar, int tb_frame, void *cb_ctx)
+{
+ struct parent_bt_lua *bt = (struct parent_bt_lua *)cb_ctx;
+
+ if (tb_frame >= PARENT_BT_LUA_LEN_MAX)
+ return 1;
+
+ bt->cnt++;
+ bt->lines[tb_frame] = ar->currentline;
+ strncpy(bt->names[tb_frame], ar->name == NULL ? "(unnamed)" : ar->name,
+ PARENT_BT_LUA_NAME_MAX - 1);
+ bt->names[tb_frame][PARENT_BT_LUA_NAME_MAX - 1] = 0;
+ strncpy(bt->sources[tb_frame], ar->source,
+ PARENT_BT_LUA_NAME_MAX - 1);
+ bt->sources[tb_frame][PARENT_BT_LUA_NAME_MAX - 1] = 0;
+
+ return 0;
+}
+
static void
-dump_parent_lua_frame(struct lua_State *L, const char *name, const char *src,
- int currentline, int tb_frame)
+lua_backtrace_foreach(struct lua_State *L, lua_backtrace_cb cb, void *cb_ctx)
{
- char buf[512];
- snprintf(buf, sizeof(buf), "%s in %s at line %i",
- name != NULL ? name : "(unnamed)",
- src, currentline);
- buf[sizeof(buf) - 1] = 0;
- lua_pushnumber(L, tb_frame);
- lua_newtable(L);
- lua_pushstring(L, "L");
- lua_pushstring(L, buf);
- lua_settable(L, -3);
- lua_settable(L, -3);
+ int lua_frame = 0, tb_frame = 0;
+ lua_Debug ar;
+ while (lua_getstack(L, lua_frame, &ar) > 0) {
+ /* Skip all following C-frames. */
+ lua_getinfo(L, "Sln", &ar);
+ if (*ar.what != 'C')
+ break;
+ if (ar.name != NULL) {
+ /* Dump frame if it is a C built-in call. */
+ if (cb(&ar, tb_frame, cb_ctx) != 0)
+ return;
+ tb_frame++;
+ }
+ lua_frame++;
+ }
+ while (lua_getstack(L, lua_frame, &ar) > 0) {
+ /* Trace Lua frame. */
+ lua_getinfo(L, "Sln", &ar);
+ if (*ar.what == 'C')
+ break;
+ if (cb(&ar, tb_frame, cb_ctx) != 0)
+ return;
+ tb_frame++;
+ lua_frame++;
+ }
}
static int
@@ -249,31 +298,9 @@ fiber_backtrace_cb(int frameno, void *frameret, const char *func, size_t offset,
* https://github.com/tarantool/tarantool/issues/5326
* will not resolved, but is possible afterwards.
*/
- if (func != NULL && strstr(func, "lj_BC_FUNCC") == func) {
+ if (func != NULL && tb_ctx->R && strstr(func, "lj_BC_FUNCC") == func) {
/* We are in the LUA vm. */
- lua_Debug ar;
- while (tb_ctx->R && lua_getstack(tb_ctx->R, tb_ctx->lua_frame, &ar) > 0) {
- /* Skip all following C-frames. */
- lua_getinfo(tb_ctx->R, "Sln", &ar);
- if (*ar.what != 'C')
- break;
- if (ar.name != NULL) {
- /* Dump frame if it is a C built-in call. */
- tb_ctx->tb_frame++;
- dump_lua_frame(L, &ar, tb_ctx->tb_frame);
- }
- tb_ctx->lua_frame++;
- }
- while (tb_ctx->R && lua_getstack(tb_ctx->R, tb_ctx->lua_frame, &ar) > 0) {
- /* Trace Lua frame. */
- lua_getinfo(tb_ctx->R, "Sln", &ar);
- if (*ar.what == 'C') {
- break;
- }
- tb_ctx->tb_frame++;
- dump_lua_frame(L, &ar, tb_ctx->tb_frame);
- tb_ctx->lua_frame++;
- }
+ lua_backtrace_foreach(tb_ctx->R, dump_lua_frame_cb, tb_ctx);
}
char buf[512];
int l = snprintf(buf, sizeof(buf), "#%-2d %p in ",
@@ -310,10 +337,10 @@ fiber_parent_backtrace_cb(int frameno, void *frameret, const char *func,
/* We are in the LUA vm. */
while (lua_frame < bt->cnt) {
tb_ctx->tb_frame++;
- dump_parent_lua_frame(L, bt->names[lua_frame],
- bt->sources[lua_frame],
- bt->lines[lua_frame],
- tb_ctx->tb_frame);
+ dump_lua_frame(L, bt->names[lua_frame],
+ bt->sources[lua_frame],
+ bt->lines[lua_frame],
+ tb_ctx->tb_frame);
lua_frame++;
}
}
@@ -338,60 +365,15 @@ fiber_parent_backtrace_cb(int frameno, void *frameret, const char *func,
static int
fiber_parent_bt_init(struct fiber *f, struct lua_State *L)
{
- int lua_frame = 0, tb_frame = 0;
- lua_Debug ar;
struct parent_bt_lua *bt = NULL;
-
- bt = (struct parent_bt_lua *)malloc(sizeof(*bt));
+ bt = (struct parent_bt_lua *)calloc(1, sizeof(*bt));
if (bt == NULL){
- diag_set(OutOfMemory, sizeof(*bt), "malloc", "bt");
+ diag_set(OutOfMemory, sizeof(*bt), "calloc", "bt");
return 1;
}
- while (tb_frame < PARENT_BT_LUA_LEN_MAX &&
- lua_getstack(L, lua_frame, &ar) > 0) {
- /* Skip all following C-frames. */
- lua_getinfo(L, "Sln", &ar);
- if (*ar.what != 'C')
- break;
- bt->names[tb_frame][0] = 0;
- bt->sources[tb_frame][0] = 0;
- if (ar.name != NULL) {
- /* Dump frame if it is a C built-in call. */
- bt->lines[tb_frame] = ar.currentline;
- strncpy(bt->names[tb_frame], ar.name,
- PARENT_BT_LUA_NAME_MAX - 1);
- bt->names[tb_frame][PARENT_BT_LUA_NAME_MAX - 1] = 0;
- strncpy(bt->sources[tb_frame], ar.source,
- PARENT_BT_LUA_NAME_MAX - 1);
- bt->sources[tb_frame][PARENT_BT_LUA_NAME_MAX - 1] = 0;
- tb_frame++;
- }
- lua_frame++;
- }
- while (tb_frame < PARENT_BT_LUA_LEN_MAX &&
- lua_getstack(L, lua_frame, &ar) > 0) {
- /* Trace Lua frame. */
- lua_getinfo(L, "Sln", &ar);
- if (*ar.what == 'C')
- break;
- bt->lines[tb_frame] = ar.currentline;
- if (ar.name != NULL) {
- strncpy(bt->names[tb_frame], ar.name,
- PARENT_BT_LUA_NAME_MAX - 1);
- } else {
- strncpy(bt->names[tb_frame], "(unnamed)",
- PARENT_BT_LUA_NAME_MAX - 1);
- }
- bt->names[tb_frame][PARENT_BT_LUA_NAME_MAX - 1] = 0;
- strncpy(bt->sources[tb_frame], ar.source,
- PARENT_BT_LUA_NAME_MAX - 1);
- bt->sources[tb_frame][PARENT_BT_LUA_NAME_MAX - 1] = 0;
- tb_frame++;
- lua_frame++;
- }
-
- bt->cnt = tb_frame;
+ bt->cnt = 0;
+ lua_backtrace_foreach(L, save_lua_frame_cb, bt);
f->storage.lua.parent_bt = bt;
return 0;
@@ -1117,7 +1099,7 @@ static const struct luaL_Reg fiberlib[] = {
{"top_enable", lbox_fiber_top_enable},
{"top_disable", lbox_fiber_top_disable},
#endif /* ENABLE_FIBER_TOP */
-#if ENABLE_BACKTRACE
+#ifdef ENABLE_BACKTRACE
{"parent_bt_enable", lbox_fiber_parent_bt_enable},
{"parent_bt_disable", lbox_fiber_parent_bt_disable},
#endif /* ENABLE_BACKTRACE */
--
2.31.1
More information about the Tarantool-patches
mailing list