backtrace: Refactor ast_bt_get_symbols so it doesn't crash

We've been seeing crashes in libbfd when we attempt to generate
a stack trace from multiple threads.  It turns out that libbfd
is NOT thread-safe.  It can cache the bfd structure and give it to
multiple threads without protecting itself.  To get around this,
we've added a global mutex around the bfd functions and also have
refactored the use of those functions to be more efficient and
to provide more information about inlined functions.

Also added a few more tests to test_pbx.c.  One just calls
ast_assert() and the other calls ast_log_backtrace().  Neither are
run by default.

WARNING:  This change necessitated changing the return value of
ast_bt_get_symbols() from an array of strings to a VECTOR of
strings.  However, the use of this function outside Asterisk is not
likely.

ASTERISK-28140

Change-Id: I79d02862ddaa2423a0809caa4b3b85c128131621
This commit is contained in:
George Joseph
2018-11-08 08:53:44 -07:00
parent fa048183aa
commit ece5f8015f
10 changed files with 318 additions and 183 deletions

View File

@@ -343,8 +343,50 @@ AST_TEST_DEFINE(segv)
return AST_TEST_FAIL;
}
AST_TEST_DEFINE(call_assert)
{
switch (cmd) {
case TEST_INIT:
info->name = "CALL_ASSERT";
info->category = "/DO_NOT_RUN/";
info->summary = "Calls ast_asert()!!! (will only be run if explicitly called)";
info->description = "Calls ast_asert()!!! (will only be run if explicitly called). "
"This test is mainly used for testing CI and tool failure scenarios.";
info->explicit_only = 1;
return AST_TEST_NOT_RUN;
case TEST_EXECUTE:
break;
}
ast_assert(0);
return AST_TEST_PASS;
}
AST_TEST_DEFINE(call_backtrace)
{
switch (cmd) {
case TEST_INIT:
info->name = "CALL_BACKTRACE";
info->category = "/DO_NOT_RUN/";
info->summary = "Calls ast_log_backtrace()!!! (will only be run if explicitly called)";
info->description = "Calls ast_log_backtrace()!!! (will only be run if explicitly called). "
"This test is mainly used for testing CI and tool failure scenarios.";
info->explicit_only = 1;
return AST_TEST_NOT_RUN;
case TEST_EXECUTE:
break;
}
ast_log_backtrace();
return AST_TEST_PASS;
}
static int unload_module(void)
{
AST_TEST_UNREGISTER(call_backtrace);
AST_TEST_UNREGISTER(call_assert);
AST_TEST_UNREGISTER(segv);
AST_TEST_UNREGISTER(pattern_match_test);
return 0;
@@ -354,6 +396,8 @@ static int load_module(void)
{
AST_TEST_REGISTER(pattern_match_test);
AST_TEST_REGISTER(segv);
AST_TEST_REGISTER(call_assert);
AST_TEST_REGISTER(call_backtrace);
return AST_MODULE_LOAD_SUCCESS;
}