Problem: no backtrace is printed on assert

Solution: add an optional dependency on libunwind, and if present
use it to print the backtrace when zmq_abort is called.
This commit is contained in:
Luca Boccassi 2016-05-06 19:00:44 +01:00
parent c1dc9d0244
commit 8045e9ae24
4 changed files with 75 additions and 4 deletions

View File

@ -277,10 +277,11 @@ endif
endif
endif
src_libzmq_la_CPPFLAGS = $(CODE_COVERAGE_CPPFLAGS)
src_libzmq_la_CFLAGS = $(CODE_COVERAGE_CFLAGS)
src_libzmq_la_CXXFLAGS = @LIBZMQ_EXTRA_CXXFLAGS@ $(CODE_COVERAGE_CXXFLAGS)
src_libzmq_la_LIBADD = $(CODE_COVERAGE_LDFLAGS)
src_libzmq_la_CPPFLAGS = $(CODE_COVERAGE_CPPFLAGS) $(LIBUNWIND_CFLAGS)
src_libzmq_la_CFLAGS = $(CODE_COVERAGE_CFLAGS) $(LIBUNWIND_CFLAGS)
src_libzmq_la_CXXFLAGS = @LIBZMQ_EXTRA_CXXFLAGS@ $(CODE_COVERAGE_CXXFLAGS) \
$(LIBUNWIND_CFLAGS)
src_libzmq_la_LIBADD = $(CODE_COVERAGE_LDFLAGS) $(LIBUNWIND_LIBS)
if USE_LIBSODIUM
src_libzmq_la_CPPFLAGS += ${sodium_CFLAGS}

View File

@ -632,6 +632,16 @@ else
AC_SUBST(pkg_config_defines, "")
fi
PKG_CHECK_MODULES(LIBUNWIND, [libunwind],
[
AC_DEFINE(HAVE_LIBUNWIND, 1, [The libunwind library is to be used])
AC_SUBST([LIBUNWIND_CFLAGS])
AC_SUBST([LIBUNWIND_LIBS])
],
[
AC_MSG_WARN([Cannot find libunwind])
])
# Subst LIBZMQ_EXTRA_CFLAGS & CXXFLAGS & LDFLAGS
AC_SUBST(LIBZMQ_EXTRA_CFLAGS)
AC_SUBST(LIBZMQ_EXTRA_CXXFLAGS)

View File

@ -81,6 +81,7 @@ void zmq::zmq_abort(const char *errmsg_)
RaiseException (0x40000015, EXCEPTION_NONCONTINUABLE, 1, extra_info);
#else
(void)errmsg_;
print_backtrace();
abort ();
#endif
}
@ -384,3 +385,61 @@ int zmq::wsa_error_to_errno (int errcode)
}
#endif
#ifdef HAVE_LIBUNWIND
#define UNW_LOCAL_ONLY
#include <libunwind.h>
#include <dlfcn.h>
#include <cxxabi.h>
void zmq::print_backtrace (void)
{
Dl_info dl_info;
unw_cursor_t cursor;
unw_context_t ctx;
unsigned frame_n = 0;
unw_getcontext (&ctx);
unw_init_local (&cursor, &ctx);
while (unw_step (&cursor) > 0) {
unw_word_t offset;
unw_proc_info_t p_info;
const char *file_name;
char *demangled_name;
char func_name[256] = "";
void *addr;
int rc;
if (unw_get_proc_info (&cursor, &p_info))
break;
addr = (void *)(p_info.start_ip + offset);
if (dladdr (addr, &dl_info) && dl_info.dli_fname)
file_name = dl_info.dli_fname;
else
file_name = "?";
rc = unw_get_proc_name (&cursor, func_name, 256, &offset);
if (rc == -UNW_ENOINFO)
strcpy(func_name, "?");
demangled_name = abi::__cxa_demangle (func_name, NULL, NULL, &rc);
printf ("#%u %p in %s (%s+0x%lx)\n", frame_n++, addr, file_name,
rc ? func_name : demangled_name, (unsigned long) offset);
free (demangled_name);
}
fflush (stdout);
}
#else
void zmq::print_backtrace (void)
{
}
#endif

View File

@ -62,6 +62,7 @@ namespace zmq
{
const char *errno_to_string (int errno_);
void zmq_abort (const char *errmsg_);
void print_backtrace (void);
}
#ifdef ZMQ_HAVE_WINDOWS