mirror of
https://github.com/curl/curl.git
synced 2026-04-11 12:01:42 +08:00
memdebug: produce stack trace dump with libbacktrace
Enable with "configure --enable-backtrace", inserts a backtrace in the memdump log when a torture test limit is reached. Closes #19657
This commit is contained in:
parent
b5265b24b0
commit
c77bed81a2
16
configure.ac
16
configure.ac
@ -1108,6 +1108,22 @@ AS_HELP_STRING([--enable-libgcc],[use libgcc when linking]),
|
||||
AC_MSG_RESULT(no)
|
||||
)
|
||||
|
||||
AC_MSG_CHECKING([whether to use libbacktrace])
|
||||
AC_ARG_WITH(backtrace,
|
||||
AS_HELP_STRING([--enable-backtrace],[use libbacktrace when linking]),
|
||||
[ case "$enableval" in
|
||||
yes)
|
||||
LIBS="-lbacktrace $LIBS"
|
||||
AC_DEFINE(USE_BACKTRACE, 1, [if libbacktrace is in use])
|
||||
AC_MSG_RESULT(yes)
|
||||
;;
|
||||
*)
|
||||
AC_MSG_RESULT(no)
|
||||
;;
|
||||
esac ],
|
||||
AC_MSG_RESULT(no)
|
||||
)
|
||||
|
||||
CURL_CHECK_LIB_XNET
|
||||
|
||||
dnl gethostbyname without lib or in the nsl lib?
|
||||
|
||||
@ -31,6 +31,10 @@
|
||||
#include "urldata.h"
|
||||
#include "curlx/fopen.h" /* for CURLX_FOPEN_LOW(), CURLX_FREOPEN_LOW() */
|
||||
|
||||
#ifdef USE_BACKTRACE
|
||||
#include "backtrace.h"
|
||||
#endif
|
||||
|
||||
/* The last 2 #include files should be in this order */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
@ -58,6 +62,9 @@ FILE *curl_dbg_logfile = NULL;
|
||||
static bool registered_cleanup = FALSE; /* atexit registered cleanup */
|
||||
static bool memlimit = FALSE; /* enable memory limit */
|
||||
static long memsize = 0; /* set number of mallocs allowed */
|
||||
#ifdef USE_BACKTRACE
|
||||
struct backtrace_state *btstate;
|
||||
#endif
|
||||
|
||||
/* LeakSantizier (LSAN) calls _exit() instead of exit() when a leak is detected
|
||||
on exit so the logfile must be closed explicitly or data could be lost.
|
||||
@ -73,6 +80,33 @@ static void curl_dbg_cleanup(void)
|
||||
}
|
||||
curl_dbg_logfile = NULL;
|
||||
}
|
||||
#ifdef USE_BACKTRACE
|
||||
static void error_callback(void *data, const char *message, int error_number)
|
||||
{
|
||||
(void)data;
|
||||
if(error_number == -1)
|
||||
curl_dbg_log("compile with -g\n\n");
|
||||
else
|
||||
curl_dbg_log("Backtrace error %d: %s\n", error_number, message);
|
||||
}
|
||||
|
||||
static int full_callback(void *data, uintptr_t pc, const char *pathname,
|
||||
int line_number, const char *function)
|
||||
{
|
||||
(void)data;
|
||||
(void)pc;
|
||||
if(pathname || function || line_number)
|
||||
curl_dbg_log("BT %s:%d -- %s\n", pathname, line_number, function);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dump_bt(void)
|
||||
{
|
||||
backtrace_full(btstate, 0, full_callback, error_callback, NULL);
|
||||
}
|
||||
#else
|
||||
#define dump_bt() /* nothing to do */
|
||||
#endif
|
||||
|
||||
/* this sets the log filename */
|
||||
void curl_dbg_memdebug(const char *logname)
|
||||
@ -88,6 +122,9 @@ void curl_dbg_memdebug(const char *logname)
|
||||
setbuf(curl_dbg_logfile, (char *)NULL);
|
||||
#endif
|
||||
}
|
||||
#ifdef USE_BACKTRACE
|
||||
btstate = backtrace_create_state(NULL, 0, error_callback, NULL);
|
||||
#endif
|
||||
if(!registered_cleanup)
|
||||
registered_cleanup = !atexit(curl_dbg_cleanup);
|
||||
}
|
||||
@ -115,6 +152,7 @@ static bool countcheck(const char *func, int line, const char *source)
|
||||
/* log to stderr also */
|
||||
curl_mfprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
|
||||
source, line, func);
|
||||
dump_bt();
|
||||
fflush(curl_dbg_logfile); /* because it might crash now */
|
||||
/* !checksrc! disable ERRNOVAR 1 */
|
||||
errno = ENOMEM;
|
||||
|
||||
@ -130,7 +130,10 @@ while(<$fileh>) {
|
||||
chomp $_;
|
||||
my $line = $_;
|
||||
$lnum++;
|
||||
if($line =~ /^LIMIT ([^ ]*):(\d*) (.*)/) {
|
||||
if($line =~ /^BT/) {
|
||||
# back-trace, ignore
|
||||
}
|
||||
elsif($line =~ /^LIMIT ([^ ]*):(\d*) (.*)/) {
|
||||
# new memory limit test prefix
|
||||
my $i = $3;
|
||||
my ($source, $linenum) = ($1, $2);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user