astobj2: assert on invalid ref and backtrace cleanup
authorScott Griepentrog <sgriepentrog@digium.com>
Fri, 18 Jul 2014 17:55:38 +0000 (17:55 +0000)
committerScott Griepentrog <sgriepentrog@digium.com>
Fri, 18 Jul 2014 17:55:38 +0000 (17:55 +0000)
If a reference count goes negative, instead of
just logging that fact, be more helpful with a
backtrace and an assert that will DO_CRASH.

This patch also removes the duplicate ao2_bt()
function and cleans up extraneous usage of the
ast_log_backtrace() call.

Review: https://reviewboard.asterisk.org/r/3765/

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@418963 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/astobj2.h
main/astobj2.c
main/logger.c
main/utils.c
res/res_pjsip_pubsub.c

index f10e1d3..692cc7c 100644 (file)
@@ -1961,9 +1961,6 @@ void *__ao2_iterator_next(struct ao2_iterator *iter) attribute_warn_unused_resul
  */
 void ao2_iterator_restart(struct ao2_iterator *iter);
 
-/* extra functions */
-void ao2_bt(void);     /* backtrace */
-
 /*! gcc __attribute__(cleanup()) functions
  * \note they must be able to handle NULL parameters because most of the
  * allocation/find functions can fail and we don't want to try to tear
index d2592ec..2dd9f05 100644 (file)
@@ -97,29 +97,6 @@ struct astobj2_rwlock {
 struct ao2_stats ao2;
 #endif
 
-#ifdef HAVE_BKTR
-#include <execinfo.h>    /* for backtrace */
-#endif
-
-void ao2_bt(void)
-{
-#ifdef HAVE_BKTR
-       int depth;
-       int idx;
-#define N1     20
-       void *addresses[N1];
-       char **strings;
-
-       depth = backtrace(addresses, N1);
-       strings = ast_bt_get_symbols(addresses, depth);
-       ast_verbose("backtrace returned: %d\n", depth);
-       for (idx = 0; idx < depth; ++idx) {
-               ast_verbose("%d: %p %s\n", idx, addresses[idx], strings[idx]);
-       }
-       ast_std_free(strings);
-#endif
-}
-
 #define INTERNAL_OBJ_MUTEX(user_data) \
        ((struct astobj2_lock *) (((char *) (user_data)) - sizeof(struct astobj2_lock)))
 
@@ -455,6 +432,9 @@ static int internal_ao2_ref(void *user_data, int delta, const char *file, int li
        if (current_value < 0) {
                ast_log(__LOG_ERROR, file, line, func,
                        "Invalid refcount %d on ao2 object %p\n", current_value, user_data);
+               ast_assert(0);
+               /* stop here even if assert doesn't DO_CRASH */
+               return -1;
        }
 
        /* last reference, destroy the object */
@@ -516,7 +496,6 @@ int __ao2_ref_debug(void *user_data, int delta, const char *tag, const char *fil
        }
 
        if (obj == NULL) {
-               ast_log_backtrace();
                ast_assert(0);
        }
 
index 86cd0d4..13d074c 100644 (file)
@@ -1759,14 +1759,14 @@ void ast_log_backtrace(void)
        }
 
        if ((strings = ast_bt_get_symbols(bt->addresses, bt->num_frames))) {
-               ast_debug(1, "Got %d backtrace record%c\n", bt->num_frames, bt->num_frames != 1 ? 's' : ' ');
+               ast_verbose("Got %d backtrace record%c\n", bt->num_frames, bt->num_frames != 1 ? 's' : ' ');
                for (i = 3; i < bt->num_frames - 2; i++) {
-                       ast_debug(1, "#%d: [%p] %s\n", i - 3, bt->addresses[i], strings[i]);
+                       ast_verbose("#%d: [%p] %s\n", i - 3, bt->addresses[i], strings[i]);
                }
 
                ast_std_free(strings);
        } else {
-               ast_debug(1, "Could not allocate memory for backtrace\n");
+               ast_verbose("Could not allocate memory for backtrace\n");
        }
        ast_bt_destroy(bt);
 #else
index b32e71b..0097487 100644 (file)
@@ -2544,7 +2544,7 @@ void __ast_assert_failed(int condition, const char *condition_str, const char *f
                condition_str, condition, line, function, file);
 
        /* Generate a backtrace for the assert */
-       ao2_bt();
+       ast_log_backtrace();
 
        /*
         * Give the logger a chance to get the message out, just in case
index cfda0ae..2b28307 100644 (file)
@@ -992,8 +992,6 @@ int ast_sip_subscription_notify(struct ast_sip_subscription *sub, void *notify_d
                        PJSIP_EVSUB_STATE_ACTIVE : PJSIP_EVSUB_STATE_TERMINATED;
        }
 
-       ast_log_backtrace();
-
        if (pjsip_evsub_notify(evsub, state, NULL, NULL, &tdata) != PJ_SUCCESS) {
                ast_free(body_text);
                return -1;