Tarantool development patches archive
 help / color / mirror / Atom feed
From: Georgy Kirichenko <georgy@tarantool.org>
To: tarantool-patches@freelists.org
Cc: Georgy Kirichenko <georgy@tarantool.org>
Subject: [tarantool-patches] [PATCH v3 4/4] Show names of Lua functions in backtraces
Date: Wed, 31 Oct 2018 13:49:13 +0300	[thread overview]
Message-ID: <54488ded8f4e686707d4c1bafb4da803f521c622.1540982711.git.georgy@tarantool.org> (raw)
In-Reply-To: <cover.1540982711.git.georgy@tarantool.org>

Trace corresponding Lua state as well as normal C stack frames while
fiber backtracing. This might be useful for debugging purposes.

Fixes: #3538
---
 src/lua/fiber.c         | 73 ++++++++++++++++++++++++++++++++++++++---
 test/app/fiber.result   | 36 ++++++++++++++++++++
 test/app/fiber.test.lua | 13 ++++++++
 3 files changed, 118 insertions(+), 4 deletions(-)

diff --git a/src/lua/fiber.c b/src/lua/fiber.c
index 147add89b..7ed341924 100644
--- a/src/lua/fiber.c
+++ b/src/lua/fiber.c
@@ -178,20 +178,80 @@ lbox_fiber_id(struct lua_State *L)
 	return 1;
 }
 
+/**
+ * Lua fiber traceback context.
+ */
+struct lua_fiber_tb_ctx {
+	/* Lua stack to push values. */
+	struct lua_State *L;
+	/* Lua stack to trace. */
+	struct lua_State *R;
+	/* Current Lua frame. */
+	int lua_frame;
+	/* Count of traced frames (both C and Lua). */
+	int tb_frame;
+};
+
 #ifdef ENABLE_BACKTRACE
+static void
+dump_lua_frame(struct lua_State *L, lua_Debug *ar, 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);
+	lua_pushnumber(L, tb_frame);
+	lua_newtable(L);
+	lua_pushstring(L, "L");
+	lua_pushstring(L, buf);
+	lua_settable(L, -3);
+	lua_settable(L, -3);
+}
+
 static int
 fiber_backtrace_cb(int frameno, void *frameret, const char *func, size_t offset, void *cb_ctx)
 {
+	struct lua_fiber_tb_ctx *tb_ctx = (struct lua_fiber_tb_ctx *)cb_ctx;
+	struct lua_State *L = tb_ctx->L;
+	if (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++;
+		}
+	}
 	char buf[512];
 	int l = snprintf(buf, sizeof(buf), "#%-2d %p in ", frameno, frameret);
 	if (func)
 		snprintf(buf + l, sizeof(buf) - l, "%s+%zu", func, offset);
 	else
 		snprintf(buf + l, sizeof(buf) - l, "?");
-	struct lua_State *L = (struct lua_State*)cb_ctx;
-	lua_pushnumber(L, frameno + 1);
+	tb_ctx->tb_frame++;
+	lua_pushnumber(L, tb_ctx->tb_frame);
+	lua_newtable(L);
+	lua_pushstring(L, "C");
 	lua_pushstring(L, buf);
 	lua_settable(L, -3);
+	lua_settable(L, -3);
 	return 0;
 }
 #endif
@@ -229,10 +289,15 @@ lbox_fiber_statof(struct fiber *f, void *cb_ctx, bool backtrace)
 
 	if (backtrace) {
 #ifdef ENABLE_BACKTRACE
+		struct lua_fiber_tb_ctx tb_ctx;
+		tb_ctx.L = L;
+		tb_ctx.R = f->storage.lua.stack;
+		tb_ctx.lua_frame = 0;
+		tb_ctx.tb_frame = 0;
 		lua_pushstring(L, "backtrace");
 		lua_newtable(L);
-		if (f != fiber())
-			backtrace_foreach(fiber_backtrace_cb, &f->ctx, L);
+		backtrace_foreach(fiber_backtrace_cb,
+				  f != fiber() ? &f->ctx : NULL, &tb_ctx);
 		lua_settable(L, -3);
 #endif /* ENABLE_BACKTRACE */
 	}
diff --git a/test/app/fiber.result b/test/app/fiber.result
index 77144e661..59aa8d5c6 100644
--- a/test/app/fiber.result
+++ b/test/app/fiber.result
@@ -849,6 +849,42 @@ f2:cancel()
 f3:cancel()
 ---
 ...
+function sf1() loop() end
+---
+...
+function sf2() sf1() end
+---
+...
+function sf3() sf2() end
+---
+...
+f1 = fiber.create(sf3)
+---
+...
+info = fiber.info()
+---
+...
+backtrace = info[f1:id()].backtrace
+---
+...
+bt_str = ''
+---
+...
+for _, b in pairs(backtrace) do bt_str = bt_str .. (b['L'] or '') end
+---
+...
+bt_str:find('sf1') ~= nil
+---
+- true
+...
+bt_str:find('loop') ~= nil
+---
+- true
+...
+bt_str:find('sf3') ~= nil
+---
+- true
+...
 -- # gh-666: nulls in output
 --
 getmetatable(fiber.info())
diff --git a/test/app/fiber.test.lua b/test/app/fiber.test.lua
index 98a136090..b9d82ef05 100644
--- a/test/app/fiber.test.lua
+++ b/test/app/fiber.test.lua
@@ -334,6 +334,19 @@ f1:cancel()
 f2:cancel()
 f3:cancel()
 
+function sf1() loop() end
+function sf2() sf1() end
+function sf3() sf2() end
+f1 = fiber.create(sf3)
+
+info = fiber.info()
+backtrace = info[f1:id()].backtrace
+bt_str = ''
+for _, b in pairs(backtrace) do bt_str = bt_str .. (b['L'] or '') end
+bt_str:find('sf1') ~= nil
+bt_str:find('loop') ~= nil
+bt_str:find('sf3') ~= nil
+
 -- # gh-666: nulls in output
 --
 getmetatable(fiber.info())
-- 
2.19.1

  parent reply	other threads:[~2018-10-31 10:49 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-10-31 10:49 [tarantool-patches] [PATCH v3 0/4] Dump lua frames for a fiber traceback Georgy Kirichenko
2018-10-31 10:49 ` [tarantool-patches] [PATCH v3 1/4] fiber: do not inline coro unwind function Georgy Kirichenko
2018-10-31 10:49 ` [tarantool-patches] [PATCH v3 2/4] Proper unwind for currently executing fiber Georgy Kirichenko
2018-10-31 10:49 ` [tarantool-patches] [PATCH v3 3/4] Use fiber lua state for triggers if possible Georgy Kirichenko
2018-10-31 10:49 ` Georgy Kirichenko [this message]
2018-11-01 12:45 ` [tarantool-patches] [PATCH v3 0/4] Dump lua frames for a fiber traceback Vladimir Davydov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54488ded8f4e686707d4c1bafb4da803f521c622.1540982711.git.georgy@tarantool.org \
    --to=georgy@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='Re: [tarantool-patches] [PATCH v3 4/4] Show names of Lua functions in backtraces' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox