Use dladdr, not libbacktrace in fast callstack decode path.

DecodeCallstackPtrFast() may be called outside the symbol processing thread,
for example in the crash handler. Using the less-capable dladdr functionality
doesn't have a big impact here. Callstack decoding in this context is used to
remove the uninteresting top part of the callstack, so that the callstack ends
at the crashing function, and not in the crash handler. Even if this
functionality would be impacted by this change, the damage done is close to
none.

The other alternative is to use locking each time a libbacktrace is to be
used, which does not seem to be worthy to do, considering that the problem
only occurs in a very rare code path.

NB everything was working when it was first implemented, because back then the
callstack decoding was still performed on the main thread, and not on a
separate, dedicated one.
This commit is contained in:
Bartosz Taudul 2022-10-08 13:22:56 +02:00
parent 94ccc37979
commit 6f9dfc8469
No known key found for this signature in database
GPG Key ID: B7FE2008B7575DF3

View File

@ -844,42 +844,24 @@ void EndCallstack()
#endif #endif
} }
static int FastCallstackDataCb( void* data, uintptr_t pc, uintptr_t lowaddr, const char* fn, int lineno, const char* function )
{
if( function )
{
strcpy( (char*)data, function );
}
else
{
const char* symname = nullptr;
auto vptr = (void*)pc;
Dl_info dlinfo;
if( dladdr( vptr, &dlinfo ) )
{
symname = dlinfo.dli_sname;
}
if( symname )
{
strcpy( (char*)data, symname );
}
else
{
*(char*)data = '\0';
}
}
return 1;
}
static void FastCallstackErrorCb( void* data, const char* /*msg*/, int /*errnum*/ )
{
*(char*)data = '\0';
}
const char* DecodeCallstackPtrFast( uint64_t ptr ) const char* DecodeCallstackPtrFast( uint64_t ptr )
{ {
static char ret[1024]; static char ret[1024];
backtrace_pcinfo( cb_bts, ptr, FastCallstackDataCb, FastCallstackErrorCb, ret ); auto vptr = (void*)ptr;
const char* symname = nullptr;
Dl_info dlinfo;
if( dladdr( vptr, &dlinfo ) && dlinfo.dli_sname )
{
symname = dlinfo.dli_sname;
}
if( symname )
{
strcpy( ret, symname );
}
else
{
*ret = '\0';
}
return ret; return ret;
} }