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 B6B066EC55; Fri, 9 Jul 2021 14:06:18 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org B6B066EC55 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1625828778; bh=jXuGZEc8zoz/d3V0XapOvUrUpqgQfuAkXWeHYsPvkCc=; h=To:Cc:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=VaVhh5aIpZujRcJdda7HicgYCnQP5rS7yne+q7YXo2x2jbl2R3bTdF+8keQbbewGF pAOug0PF4dyxVGWNsxpjQUtDYI/1bpBgRZlRRxx1R/5BTJ4t4ndv3TDREz/3dPlhZB 1f4bxIRMgQ5Yv12HplbAKmZRmppOG06L1HWGTvAk= Received: from smtp33.i.mail.ru (smtp33.i.mail.ru [94.100.177.93]) (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 91BA66EC56 for ; Fri, 9 Jul 2021 14:04:19 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 91BA66EC56 Received: by smtp33.i.mail.ru with esmtpa (envelope-from ) id 1m1oIs-0008Ob-Lo; Fri, 09 Jul 2021 14:04:19 +0300 To: gorcunov@tarantool.org, alyapunov@tarantool.org Cc: tarantool-patches@dev.tarantool.org, Egor Elchinov Date: Fri, 9 Jul 2021 14:03:53 +0300 Message-Id: X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-7564579A: EEAE043A70213CC8 X-77F55803: 4F1203BC0FB41BD954DFF1DC42D673FBBD367E85DD81335AB0D1C33BC341B12B182A05F53808504002FC6A5DA59AF2C6625633D6855BA8B86C380D8BB3B94E13DC87EDEE492DBEC5 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE73B44982FA5E78411EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637389D8DDD54F43F7A8638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D82C00C7E2E48EAD449EB56041566256B0117882F4460429724CE54428C33FAD305F5C1EE8F4F765FCAA867293B0326636D2E47CDBA5A96583BD4B6F7A4D31EC0BC014FD901B82EE079FA2833FD35BB23D27C277FBC8AE2E8BAA867293B0326636D2E47CDBA5A96583BA9C0B312567BB2376E601842F6C81A19E625A9149C048EEFAD5A440E159F97D269E641683F5DD3FD8FC6C240DEA7642DBF02ECDB25306B2B78CF848AE20165D0A6AB1C7CE11FEE3B5C78E0E843E24DABA3038C0950A5D36B5C8C57E37DE458B0BC6067A898B09E46D1867E19FE14079C09775C1D3CA48CF3D321E7403792E342EB15956EA79C166A417C69337E82CC275ECD9A6C639B01B78DA827A17800CE73A6989AD488FD87D731C566533BA786AA5CC5B56E945C8DA X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C414F749A5E30D975C44FE9905A23AFB60CAF449E13A4C81BF271F5668A2AEB9B79C2B6934AE262D3EE7EAB7254005DCED114C52B35DBB74F4E7EAB7254005DCEDA5DF9383870C0FED1E0A4E2319210D9B64D260DF9561598FCFFBF5018520E39817A45118377F5F9E8E8E86DC7131B365E7726E8460B7C23C X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D346B1FF97F6D0959A20D6FCB61A5D1E17C006A9010D59BC0860477EDF14FA755F7F032421483ADE1A71D7E09C32AA3244CFD33CF2DD6CD3D4F3D74FE0E8D9C59B3C3B3ADDA61883BB5927AC6DF5659F194 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojbL9S8ysBdXhfGtq77ANurZMdV0K+N3vA X-Mailru-Sender: 11C2EC085EDE56FAC07928AF2646A769A03E2FB30D63BABA625633D6855BA8B838066306E4938E9F58570E9BDA2331C06F53C80213D1719C2C26F88BABE1618CA23003C376F5F1387402F9BA4338D657ED14614B50AE0675 X-Mras: Ok Subject: [Tarantool-patches] [PATCH v2 4/4] 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 Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" 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