diff --git a/libs/freetdm/Makefile.am b/libs/freetdm/Makefile.am index bfd68a17eb..55d8865dec 100644 --- a/libs/freetdm/Makefile.am +++ b/libs/freetdm/Makefile.am @@ -79,7 +79,8 @@ libfreetdm_la_SOURCES = \ $(SRC)/ftdm_buffer.c \ $(SRC)/ftdm_threadmutex.c \ $(SRC)/ftdm_dso.c \ - $(SRC)/ftdm_cpu_monitor.c + $(SRC)/ftdm_cpu_monitor.c \ + $(SRC)/ftdm_backtrace.c library_include_HEADERS = \ $(SRC)/include/freetdm.h \ diff --git a/libs/freetdm/configure.ac b/libs/freetdm/configure.ac index b4c9cda8ab..f72a6268a8 100644 --- a/libs/freetdm/configure.ac +++ b/libs/freetdm/configure.ac @@ -136,7 +136,7 @@ AC_CHECK_LIB([dl], [dlopen]) AC_CHECK_LIB([pthread], [pthread_create]) AC_CHECK_LIB([m], [cos]) -AC_CHECK_HEADERS([netdb.h sys/select.h]) +AC_CHECK_HEADERS([netdb.h sys/select.h execinfo.h]) AC_CHECK_FUNC([gethostbyname_r], [], [AC_CHECK_LIB([nsl], [gethostbyname_r])] diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 35b8d9b01a..64d34f232c 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -35,13 +35,6 @@ #include "freetdm.h" //#define CUDATEL_DEBUG -#ifdef CUDATEL_DEBUG -#ifndef _BSD_SOURCE -#define _BSD_SOURCE -#endif -#include -#include -#endif #ifndef __FUNCTION__ #define __FUNCTION__ __SWITCH_FUNC__ @@ -499,6 +492,21 @@ static switch_status_t channel_on_destroy(switch_core_session_t *session) return SWITCH_STATUS_SUCCESS; } +#ifdef CUDATEL_DEBUG +struct cudatel_trace_priv { + const char *name; + int span_id; + int chan_id; +}; + +static void cudatel_trace(const int tid, const void *addr, const char *symbol, void *priv) +{ + struct cudatel_trace_priv *data = priv; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%d:%d][tid:%d] %s -> %s\n", + data->span_id, data->chan_id, tid, data->name, symbol); +} +#endif + static switch_status_t channel_on_hangup(switch_core_session_t *session) { switch_channel_t *channel = NULL; @@ -558,19 +566,11 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) #ifdef CUDATEL_DEBUG { - pid_t tid = 0; - size_t size = 0; - char **symbols = NULL; - void *stacktrace[50]; - int si = 0; - size = backtrace(stacktrace, ftdm_array_len(stacktrace)); - symbols = backtrace_symbols(stacktrace, size); - tid = syscall(SYS_gettid); - for (si = 0; si < size; si++) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%d:%d][tid:%d] %s -> %s\n", - span_id, chan_id, tid, name, symbols[si]); - } - free(symbols); + struct cudatel_trace_priv trace_data; + trace_data.name = name; + trace_data.span_id = span_id; + trace_data.chan_id = chan_id; + ftdm_backtrace_walk(&cudatel_trace, &trace_data); } #endif diff --git a/libs/freetdm/src/ftdm_backtrace.c b/libs/freetdm/src/ftdm_backtrace.c new file mode 100644 index 0000000000..70eef159d1 --- /dev/null +++ b/libs/freetdm/src/ftdm_backtrace.c @@ -0,0 +1,75 @@ +/* + * + * + */ +#define _BSD_SOURCE +#include "private/ftdm_core.h" + +#ifdef HAVE_EXECINFO_H +#include +#include +#include +#include + +#define FTDM_BACKTRACE_MAX 50 + +FT_DECLARE(ftdm_status_t) ftdm_backtrace_walk(void (* callback)(const int tid, const void *addr, const char *symbol, void *priv), void *priv) +{ + void *stacktrace[FTDM_BACKTRACE_MAX]; + char **symbols = NULL; + size_t size = 0; + pid_t tid = 0; + int si = 0; + + if (!callback) { + return FTDM_EINVAL; + } + + tid = syscall(SYS_gettid); + + size = backtrace(stacktrace, ftdm_array_len(stacktrace)); + symbols = backtrace_symbols(stacktrace, size); + + for (si = 0; si < size; si++) { + callback(tid, stacktrace[si], symbols[si], priv); + } + + free(symbols); + return FTDM_SUCCESS; +} + +#else /* !HAVE_EXECINFO_H */ + +FT_DECLARE(ftdm_status_t) ftdm_backtrace_walk(void (* callback)(const int tid, const void *addr, const char *symbol, void *priv), void *priv) +{ + ftdm_log(FTDM_LOG_DEBUG, "Stack traces are not available on this platform!\n"); + return FTDM_NOTIMPL; +} + +#endif + + +static void span_backtrace(const int tid, const void *addr, const char *symbol, void *priv) +{ + ftdm_span_t *span = priv; + ftdm_log(FTDM_LOG_DEBUG, "[%d][tid:%d] %p -> %s\n", + ftdm_span_get_id(span), tid, addr, symbol); +} + +FT_DECLARE(ftdm_status_t) ftdm_backtrace_span(ftdm_span_t *span) +{ + return ftdm_backtrace_walk(&span_backtrace, span); +} + + +static void chan_backtrace(const int tid, const void *addr, const char *symbol, void *priv) +{ + ftdm_channel_t *chan = priv; + ftdm_log(FTDM_LOG_DEBUG, "[%d:%d][tid:%d] %p -> %s\n", + ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan), tid, addr, symbol); +} + +FT_DECLARE(ftdm_status_t) ftdm_backtrace_chan(ftdm_channel_t *chan) +{ + return ftdm_backtrace_walk(&chan_backtrace, chan); +} diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index b178784239..d984f5b1c8 100755 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -1814,6 +1814,40 @@ FT_DECLARE(void) ftdm_global_set_config_directory(const char *path); /*! \brief Check if the FTDM library is initialized and running */ FT_DECLARE(ftdm_bool_t) ftdm_running(void); +/** + * Generate a stack trace and invoke a callback function for each entry + * \param[in] callback Callback function, that is invoked for each stack symbol + * \param[in] priv (User-)Private data passed to the callback + * \retval + * FTDM_SUCCESS On success + * FTDM_NOTIMPL Backtraces are not available + * FTDM_EINVAL Invalid arguments (callback was NULL) + */ +FT_DECLARE(ftdm_status_t) ftdm_backtrace_walk(void (* callback)(const int tid, const void *addr, const char *symbol, void *priv), void *priv); + +/** + * Convenience function to print a backtrace for a span. + * \note The backtrace is generated with FTDM_LOG_DEBUG log level. + * \param[in] span Span object + * \retval + * FTDM_SUCCESS On success + * FTDM_NOTIMPL Backtraces are not available + * FTDM_EINVAL Invalid arguments (e.g. span was NULL) + */ +FT_DECLARE(ftdm_status_t) ftdm_backtrace_span(ftdm_span_t *span); + +/** + * Convenience function to print a backtrace for a channel. + * \note The backtrace is generated with FTDM_LOG_DEBUG log level. + * \param[in] chan Channel object + * \retval + * FTDM_SUCCESS On success + * FTDM_NOTIMPL Backtraces are not available + * FTDM_EINVAL Invalid arguments (e.g. chan was NULL) + */ +FT_DECLARE(ftdm_status_t) ftdm_backtrace_chan(ftdm_channel_t *chan); + + FT_DECLARE_DATA extern ftdm_logger_t ftdm_log; /*! \brief Basic transcoding function prototype */ diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 6418baa3be..7cd8aacafb 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -104,10 +104,6 @@ #include #endif -#ifdef __linux__ -#include -#endif - #include #include #include