From b18dd47f50e817be5ef91013c5514fd6226d836d Mon Sep 17 00:00:00 2001
From: Georgy Kirichenko <georgy@tarantool.org>
Date: Thu, 2 Nov 2017 22:36:07 +0300
Subject: [PATCH] Introduce backtrace=true option to fiber.info()

Symbol resolving can be expensive. Introduce an option for fiber.info():

    fiber.info({ backtrace = true })
    fiber.info({ bt = true })

Fixes #2878
---
 src/lua/fiber.c         | 42 +++++++++++++++++++++++++++++++++--------
 test/app/fiber.result   | 14 ++++++++++++++
 test/app/fiber.test.lua |  5 +++++
 3 files changed, 53 insertions(+), 8 deletions(-)

diff --git a/src/lua/fiber.c b/src/lua/fiber.c
index f6abfdbd2a..fdbd8fa4c2 100644
--- a/src/lua/fiber.c
+++ b/src/lua/fiber.c
@@ -197,7 +197,7 @@ fiber_backtrace_cb(int frameno, void *frameret, const char *func, size_t offset,
 #endif
 
 static int
-lbox_fiber_statof(struct fiber *f, void *cb_ctx)
+lbox_fiber_statof(struct fiber *f, void *cb_ctx, bool backtrace)
 {
 	struct lua_State *L = (struct lua_State *) cb_ctx;
 
@@ -227,26 +227,52 @@ lbox_fiber_statof(struct fiber *f, void *cb_ctx)
 	lua_settable(L, -3);
 	lua_settable(L, -3);
 
+	if (backtrace) {
 #ifdef ENABLE_BACKTRACE
-	lua_pushstring(L, "backtrace");
-	lua_newtable(L);
-	if (f != fiber())
-		backtrace_foreach(fiber_backtrace_cb, &f->ctx, L);
-	lua_settable(L, -3);
+		lua_pushstring(L, "backtrace");
+		lua_newtable(L);
+		if (f != fiber())
+			backtrace_foreach(fiber_backtrace_cb, &f->ctx, L);
+		lua_settable(L, -3);
 #endif /* ENABLE_BACKTRACE */
-
+	}
 	lua_settable(L, -3);
 	return 0;
 }
 
+static int
+lbox_fiber_statof_bt(struct fiber *f, void *cb_ctx)
+{
+	return lbox_fiber_statof(f, cb_ctx, true);
+}
+
+static int
+lbox_fiber_statof_nobt(struct fiber *f, void *cb_ctx)
+{
+	return lbox_fiber_statof(f, cb_ctx, false);
+}
+
 /**
  * Return fiber statistics.
  */
 static int
 lbox_fiber_info(struct lua_State *L)
 {
+	bool do_backtrace = true;
+	if (lua_istable(L, 1)) {
+		lua_pushstring(L, "backtrace");
+		lua_gettable(L, 1);
+		if (lua_isnil(L, -1)){
+			lua_pop(L, 1);
+			lua_pushstring(L, "bt");
+			lua_gettable(L, 1);
+		}
+		if (!lua_isnil(L, -1))
+			do_backtrace = lua_toboolean(L, -1);
+		lua_pop(L, 1);
+	}
 	lua_newtable(L);
-	fiber_stat(lbox_fiber_statof, L);
+	fiber_stat(do_backtrace ? lbox_fiber_statof_bt : lbox_fiber_statof_nobt, L);
 	lua_createtable(L, 0, 1);
 	lua_pushliteral(L, "mapping"); /* YAML will use block mode */
 	lua_setfield(L, -2, LUAL_SERIALIZE);
diff --git a/test/app/fiber.result b/test/app/fiber.result
index 699bf3d740..08d38ef7be 100644
--- a/test/app/fiber.result
+++ b/test/app/fiber.result
@@ -826,6 +826,20 @@ info[f3:id()] ~= nil
 ---
 - true
 ...
+info = fiber.info({bt = false})
+---
+...
+info[f1:id()].backtrace == nil
+---
+- true
+...
+info = fiber.info({backtrace = false})
+---
+...
+info[f1:id()].backtrace == nil
+---
+- true
+...
 f1:cancel()
 ---
 ...
diff --git a/test/app/fiber.test.lua b/test/app/fiber.test.lua
index e9da622d2d..ad3da09916 100644
--- a/test/app/fiber.test.lua
+++ b/test/app/fiber.test.lua
@@ -325,6 +325,11 @@ info[f1:id()] ~= nil
 info[f2:id()] ~= nil
 info[f3:id()] ~= nil
 
+info = fiber.info({bt = false})
+info[f1:id()].backtrace == nil
+info = fiber.info({backtrace = false})
+info[f1:id()].backtrace == nil
+
 f1:cancel()
 f2:cancel()
 f3:cancel()
-- 
GitLab