From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 982BD2C7FA for ; Wed, 31 Oct 2018 06:49:10 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id YY_8QYhef7wh for ; Wed, 31 Oct 2018 06:49:10 -0400 (EDT) Received: from smtp61.i.mail.ru (smtp61.i.mail.ru [217.69.128.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id 4F3A22C77E for ; Wed, 31 Oct 2018 06:49:10 -0400 (EDT) From: Georgy Kirichenko Subject: [tarantool-patches] [PATCH v3 4/4] Show names of Lua functions in backtraces Date: Wed, 31 Oct 2018 13:49:13 +0300 Message-Id: <54488ded8f4e686707d4c1bafb4da803f521c622.1540982711.git.georgy@tarantool.org> In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-subscribe: List-owner: List-post: List-archive: To: tarantool-patches@freelists.org Cc: Georgy Kirichenko 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