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 C3CAE6EC40; Thu, 1 Jul 2021 18:58:43 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org C3CAE6EC40 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1625155123; bh=RePxYUzv8qO5FjmY8YHYKmwFXkG1USuvLcyifVW8fkM=; 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=gAbNzhf+cJdT7bDrGdWb4c/Ti3DL0eUdXAIEM5Yad1Jy1CI3U9dw2LTUApEkLKaGi l0fOq0z8VasJ2ccS819GOOoT/+NSeaRHDQksScYvy5XyHq1pigxQPkJ9hUTU3ZX0sO xVyqU7IyEXgg9EE6IwzjU7nHtPOjfNRG/r7qYndw= Received: from smtp31.i.mail.ru (smtp31.i.mail.ru [94.100.177.91]) (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 DEC546EC5D for ; Thu, 1 Jul 2021 18:55:28 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org DEC546EC5D Received: by smtp31.i.mail.ru with esmtpa (envelope-from ) id 1lyz2F-0006YJ-HN; Thu, 01 Jul 2021 18:55:28 +0300 To: tarantool-patches@dev.tarantool.org Date: Thu, 1 Jul 2021 18:54:50 +0300 Message-Id: <591c80e744fd1c7c70dd53cc49df9e08c905a7e1.1625153622.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-4EC0790: 10 X-7564579A: B8F34718100C35BD X-77F55803: 4F1203BC0FB41BD954DFF1DC42D673FB703477AD6D36A6E3C7EF2853D6A1C7C1182A05F538085040809F7897A0C43B4CDB62BAADC54039C4110A7E6FE63EC1F84C4D5A6677FC1F5D X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE73B44982FA5E78411EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F79006375E280A1EC162AD7D8638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D811141CE187D9B8FF8D56DDF0F72E721A117882F4460429724CE54428C33FAD305F5C1EE8F4F765FCAA867293B0326636D2E47CDBA5A96583BD4B6F7A4D31EC0BC014FD901B82EE079FA2833FD35BB23D27C277FBC8AE2E8BAA867293B0326636D2E47CDBA5A96583BA9C0B312567BB2376E601842F6C81A19E625A9149C048EE599709FD55CB46A62D242C3BD2E3F4C64AD6D5ED66289B52698AB9A7B718F8C46E0066C2D8992A16725E5C173C3A84C31EBBAFDAEF65C2E6BA3038C0950A5D36B5C8C57E37DE458B0BC6067A898B09E46D1867E19FE14079C09775C1D3CA48CF3D321E7403792E342EB15956EA79C166A417C69337E82CC275ECD9A6C639B01B78DA827A17800CE7668E9DCFC093FD7B731C566533BA786AA5CC5B56E945C8DA X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C414F749A5E30D975CA007D7800FCDDA2749F87A6773CEA0E99C4D882CBFDEF24E9C2B6934AE262D3EE7EAB7254005DCED114C52B35DBB74F4E7EAB7254005DCEDA5DF9383870C0FED1E0A4E2319210D9B64D260DF9561598F01A9E91200F654B05FE3B9244D85F0BB8E8E86DC7131B365E7726E8460B7C23C X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D34C5CF6F4B28551E3FE68BB2CF175869166AF2809179563FBDF1EDEA0AFC0E1787F5FCD8A6FC151A9E1D7E09C32AA3244CD0EAEC3E1C3D07372806DCBBFFE1E69D69B6CAE0477E908D83B48618A63566E0 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojbL9S8ysBdXgzbH4gLt0SRqUdcLkHr9vF X-Mailru-Sender: EFA0F3A8419EF2166B053C73E674FFD5E4176D4BE6E3C186096051B6A4F62936E2527C969975515C67F54F2D6EFFC80BC77752E0C033A69E17841C44D9B5D58765F2F89A5AFDB6F16C18EFA0BB12DBB0 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: gorcunov@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