From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id C0BC26EC40; Thu, 1 Jul 2021 23:29:16 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org C0BC26EC40 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1625171356; bh=ajFwIa8+r8ZLwVnmBq377CaulCVL/aRNk0doL4pTJww=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=zhAm7Un2NMkAuDrL2sM8APqz/UWeSSxWgm2r1d3kq7Qr+RoE50TpWRChdJTIZ2HtR zUUraufQCBw4z+IVQChkSAYvyQlM2lmWVEYvf8Db8pGU938FSKdi//CV+B7uHH2LNG X/E/9cAK7Wkt0pVANgdHTYQ/NFFl3MV6NrmCwEFY= Received: from smtp60.i.mail.ru (smtp60.i.mail.ru [217.69.128.40]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 465296EC5D for ; Thu, 1 Jul 2021 23:25:55 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 465296EC5D Received: by smtp60.i.mail.ru with esmtpa (envelope-from ) id 1lz3Fx-0006gg-VW; Thu, 01 Jul 2021 23:25:54 +0300 To: gorcunov@tarantool.org, alyapunov@tarantool.org, skaplun@tarantool.org Date: Thu, 1 Jul 2021 23:24:45 +0300 Message-Id: <591c80e744fd1c7c70dd53cc49df9e08c905a7e1.1625170992.git.elchinov.es@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD954DFF1DC42D673FB96E19CC2B9345E2B1F8975EC27617E56182A05F538085040558E3BA0E456B4A091052167825FBB8294C73A303A070B72C3C7D51F26C19ECD X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7BC08626EA5717D14EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637B12C6B1582157D838638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D81BA2FB077469BDBCD22C0654670DC1F1117882F4460429724CE54428C33FAD305F5C1EE8F4F765FCAA867293B0326636D2E47CDBA5A96583BD4B6F7A4D31EC0BC014FD901B82EE079FA2833FD35BB23D27C277FBC8AE2E8BAA867293B0326636D2E47CDBA5A96583BA9C0B312567BB2376E601842F6C81A19E625A9149C048EEFAD5A440E159F97D269E641683F5DD3FD8FC6C240DEA7642DBF02ECDB25306B2B78CF848AE20165D0A6AB1C7CE11FEE3DA7BFA4571439BB2AD7EC71F1DB88427C4224003CC836476EA7A3FFF5B025636E2021AF6380DFAD1A18204E546F3947CB11811A4A51E3B096D1867E19FE1407959CC434672EE6371089D37D7C0E48F6C8AA50765F79006379FC65886B7F75608EFF80C71ABB335746BA297DBC24807EABDAD6C7F3747799A X-B7AD71C0: AC4F5C86D027EB782CDD5689AFBDA7A2368A440D3B0F6089093C9A16E5BC824A2A04A2ABAA09D25379311020FFC8D4ADD39CE08E0D58FA7826045B89D8FBBAD2 X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C414F749A5E30D975CBCA6440478D4BA4603D3AECAA8979008C2FC8888FAA355089C2B6934AE262D3EE7EAB7254005DCED114C52B35DBB74F4E7EAB7254005DCEDA5DF9383870C0FED1E0A4E2319210D9B64D260DF9561598F01A9E91200F654B05FE3B9244D85F0BB8E8E86DC7131B365E7726E8460B7C23C X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D34A5112A9AECFE11B1460E76E6FD5B217D8D22C81F75287C6FB164BCF4B9738A5BC4900C4AD051AFBA1D7E09C32AA3244CA2F08190AE13E5778162D1CDE0BBFB24E646F07CC2D4F3D883B48618A63566E0 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2bioj1IeO6ekkXq2V/5JdAFH39w== X-Mailru-Sender: EFA0F3A8419EF2166B053C73E674FFD5517D874000C3CD021BFBD213B7E0254BE2527C969975515C67F54F2D6EFFC80BC77752E0C033A69E17841C44D9B5D58765F2F89A5AFDB6F16C18EFA0BB12DBB0 X-Mras: Ok Subject: [Tarantool-patches] [PATCH 7/7] fiber: refactor C backtrace and add changelog X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Egor Elchinov via Tarantool-patches Reply-To: eelchinov@tarantool.org Cc: tarantool-patches@dev.tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" From: Egor Elchinov From: Egor Elchinov Backtrace cache support and cxx demangling added. DWARF version and lua test fixed to support specific platforms. Changelog added. Closes: #4002 --- .../gh-4002-fiber-creation-backtrace.md | 8 + src/lib/core/backtrace.cc | 164 +++++++++++++----- .../gh-4002-fiber-creation-backtrace.result | 4 +- .../gh-4002-fiber-creation-backtrace.test.lua | 4 +- 4 files changed, 132 insertions(+), 48 deletions(-) create mode 100644 changelogs/unreleased/gh-4002-fiber-creation-backtrace.md diff --git a/changelogs/unreleased/gh-4002-fiber-creation-backtrace.md b/changelogs/unreleased/gh-4002-fiber-creation-backtrace.md new file mode 100644 index 000000000..1e1ac177a --- /dev/null +++ b/changelogs/unreleased/gh-4002-fiber-creation-backtrace.md @@ -0,0 +1,8 @@ +## feature/fiber + + * Added new subtable `parent_backtrace` to the `fiber.info()` + containing C and Lua backtrace chunks of fiber creation. + * Added `fiber.parent_bt_enable()` and `fiber.parent_bt_disable()` + options in order to switch on/off the ability to collect + parent backtraces for newly created fibers and to + show/hide `parent_backtrace` subtables in the `fiber.info()`. diff --git a/src/lib/core/backtrace.cc b/src/lib/core/backtrace.cc index f97c4c0a9..c82aa27af 100644 --- a/src/lib/core/backtrace.cc +++ b/src/lib/core/backtrace.cc @@ -47,7 +47,6 @@ #include #ifdef TARGET_OS_DARWIN -#include #include #endif @@ -79,19 +78,29 @@ backtrace_proc_cache_clear(void) proc_cache = NULL; } -const char * -get_proc_name(unw_cursor_t *unw_cur, unw_word_t *offset, bool skip_cache) +int +backtrace_proc_cache_find(unw_word_t ip, const char **name, unw_word_t *offset) { - static __thread char proc_name[BACKTRACE_NAME_MAX]; - unw_word_t ip; - unw_get_reg(unw_cur, UNW_REG_IP, &ip); + struct proc_cache_entry *entry; + mh_int_t k; - if (skip_cache) { - unw_get_proc_name(unw_cur, proc_name, sizeof(proc_name), - offset); - return proc_name; + if (proc_cache != NULL) { + k = mh_i64ptr_find(proc_cache, ip, NULL); + if (k != mh_end(proc_cache)) { + entry = (struct proc_cache_entry *) + mh_i64ptr_node(proc_cache, k)->val; + *offset = entry->offset; + *name = entry->name; + return 0; + } } + return -1; +} + +int +backtrace_proc_cache_put(unw_word_t ip, const char *name, unw_word_t offset) +{ struct proc_cache_entry *entry; struct mh_i64ptr_node_t node; mh_int_t k; @@ -99,39 +108,51 @@ get_proc_name(unw_cursor_t *unw_cur, unw_word_t *offset, bool skip_cache) if (proc_cache == NULL) { region_create(&cache_region, &cord()->slabc); proc_cache = mh_i64ptr_new(); - if (proc_cache == NULL) { - unw_get_proc_name(unw_cur, proc_name, sizeof(proc_name), - offset); - goto error; - } + if (proc_cache == NULL) + return -1; + } + + size_t size; + entry = region_alloc_object(&cache_region, typeof(*entry), + &size); + if (entry == NULL) + return -1; + + node.key = ip; + node.val = entry; + entry->offset = offset; + snprintf(entry->name, BACKTRACE_NAME_MAX, "%s", name); + + k = mh_i64ptr_put(proc_cache, &node, NULL, NULL); + if (k == mh_end(proc_cache)) { + size_t used = region_used(&cache_region); + region_truncate(&cache_region, used - size); + return -1; } - k = mh_i64ptr_find(proc_cache, ip, NULL); - if (k != mh_end(proc_cache)) { - entry = (struct proc_cache_entry *) - mh_i64ptr_node(proc_cache, k)->val; - snprintf(proc_name, BACKTRACE_NAME_MAX, "%s", entry->name); - *offset = entry->offset; - } else { + return 0; +} + +const char * +get_proc_name(unw_cursor_t *unw_cur, unw_word_t *offset, bool skip_cache) +{ + static __thread char proc_name[BACKTRACE_NAME_MAX]; + const char *cache_name; + unw_word_t ip; + + if (skip_cache) { unw_get_proc_name(unw_cur, proc_name, sizeof(proc_name), offset); - size_t size; - entry = region_alloc_object(&cache_region, typeof(*entry), - &size); - if (entry == NULL) - goto error; - node.key = ip; - node.val = entry; - snprintf(entry->name, BACKTRACE_NAME_MAX, "%s", proc_name); - entry->offset = *offset; - - k = mh_i64ptr_put(proc_cache, &node, NULL, NULL); - if (k == mh_end(proc_cache)) { - free(entry); - goto error; - } + return proc_name; } -error: + + unw_get_reg(unw_cur, UNW_REG_IP, &ip); + if (backtrace_proc_cache_find(ip, &cache_name, offset) == 0) { + return cache_name; + } + + unw_get_proc_name(unw_cur, proc_name, sizeof(proc_name), offset); + backtrace_proc_cache_put(ip, proc_name, *offset); return proc_name; } @@ -450,7 +471,25 @@ backtrace_collect_ip(void **ip_buf, int limit) #ifndef TARGET_OS_DARWIN unw_backtrace(ip_buf, limit); #else - backtrace(ip_buf, limit); + /* + * This dumb implementation was chosen because the DARWIN + * lacks unw_backtrace() routine from libunwind and + * usual backtrace() from has less capabilities + * than the libunwind version which uses DWARF. + */ + unw_cursor_t unw_cur; + unw_context_t unw_ctx; + int frame_no = 0; + unw_word_t ip; + + unw_getcontext(&unw_ctx); + unw_init_local(&unw_cur, &unw_ctx); + + while (frame_no < limit && unw_step(&unw_cur) > 0) { + unw_get_reg(&unw_cur, UNW_REG_IP, &ip); + ip_buf[frame_no] = (void *)ip; + ++frame_no; + } #endif } @@ -469,12 +508,15 @@ void backtrace_foreach_ip(backtrace_cb cb, void **ip_buf, int limit, void *cb_ctx) { + int demangle_status; + char *demangle_buf = NULL; + size_t demangle_buf_len = 0; #ifndef TARGET_OS_DARWIN char proc_name[BACKTRACE_NAME_MAX]; unw_word_t ip = 0, offset = 0; unw_proc_info_t pi; int frame_no, ret = 0; - char *proc = NULL; + const char *proc = NULL; unw_accessors_t *acc = unw_get_accessors(unw_local_addr_space); @@ -487,21 +529,37 @@ backtrace_foreach_ip(backtrace_cb cb, void **ip_buf, int limit, frame_no++) { ip = (unw_word_t)ip_buf[frame_no]; - if (acc->get_proc_name == NULL) { + if (backtrace_proc_cache_find(ip, &proc, &offset) == 0) { + ret = 0; + } else if (acc->get_proc_name == NULL) { ret = unw_get_proc_info_by_ip(unw_local_addr_space, ip, &pi, NULL); offset = ip - pi.start_ip; + proc = NULL; + backtrace_proc_cache_put(ip, proc, offset); } else { ret = acc->get_proc_name(unw_local_addr_space, ip, proc_name, sizeof(proc_name), &offset, NULL); proc = proc_name; + backtrace_proc_cache_put(ip, proc, offset); + } + + if (proc != NULL) { + char *cxxname = abi::__cxa_demangle(proc, demangle_buf, + &demangle_buf_len, + &demangle_status); + if (cxxname != NULL) { + demangle_buf = cxxname; + proc = cxxname; + } } if (ret != 0 || cb(frame_no - 1, (void *)ip, proc, (size_t)offset, cb_ctx) != 0) break; } + free(demangle_buf); if (ret != 0) say_debug("unwinding error: %s", unw_strerror(ret)); #else @@ -509,17 +567,35 @@ backtrace_foreach_ip(backtrace_cb cb, void **ip_buf, int limit, void *ip = NULL; size_t offset = 0; Dl_info dli; + const char *proc = NULL; for (frame_no = 1; frame_no < limit && ip_buf[frame_no] != NULL; ++frame_no) { ip = ip_buf[frame_no]; - ret = dladdr(ip, &dli); - offset = (char *)ip - (char *)dli.dli_saddr; + if (backtrace_proc_cache_find((unw_word_t)ip, &proc, + &offset) == 0) { + ret = 0; + } else { + ret = dladdr(ip, &dli); + offset = (char *)ip - (char *)dli.dli_saddr; + proc = dli.dli_sname; + backtrace_proc_cache_put((unw_word_t)ip, proc, offset); + } - if (cb(frame_no - 1, ip, dli.dli_sname, offset, cb_ctx) != 0) + if (proc != NULL) { + char *cxxname = abi::__cxa_demangle(proc, demangle_buf, + &demangle_buf_len, + &demangle_status); + if (cxxname != NULL) { + demangle_buf = cxxname; + proc = cxxname; + } + } + if (cb(frame_no - 1, ip, proc, offset, cb_ctx) != 0) break; } + free(demangle_buf); if (ret == 0) say_debug("unwinding error: %i", ret); #endif diff --git a/test/app/gh-4002-fiber-creation-backtrace.result b/test/app/gh-4002-fiber-creation-backtrace.result index 6a075911d..91b0cb9ce 100644 --- a/test/app/gh-4002-fiber-creation-backtrace.result +++ b/test/app/gh-4002-fiber-creation-backtrace.result @@ -9,10 +9,10 @@ test_run = require('test_run').new() | --- | ... -local stack_len = 0 +stack_len = 0 | --- | ... -local parent_stack_len = 0 +parent_stack_len = 0 | --- | ... diff --git a/test/app/gh-4002-fiber-creation-backtrace.test.lua b/test/app/gh-4002-fiber-creation-backtrace.test.lua index 79a516860..3c39bb48e 100644 --- a/test/app/gh-4002-fiber-creation-backtrace.test.lua +++ b/test/app/gh-4002-fiber-creation-backtrace.test.lua @@ -2,8 +2,8 @@ yaml = require('yaml') fiber = require('fiber') test_run = require('test_run').new() -local stack_len = 0 -local parent_stack_len = 0 +stack_len = 0 +parent_stack_len = 0 test_run:cmd('setopt delimiter ";"') foo = function() -- 2.31.1