]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Add some asserts that were handy when looking for a stasis cache problem.
authorRichard Mudgett <rmudgett@digium.com>
Fri, 4 Apr 2014 17:53:20 +0000 (17:53 +0000)
committerRichard Mudgett <rmudgett@digium.com>
Fri, 4 Apr 2014 17:53:20 +0000 (17:53 +0000)
* Assert if a channel is destroyed but has the snapshot staging flag set.
In this case the final channel destruction snapshot would never get taken.

* Assert if what we just got out of the stasis cache is not what we were
looking for.  This assert would have saved several days searching for a
bug and a lot of my hair.

* Assert if the music on hold message posts could not find the associated
channel.  A crash will happen later when manager tries to send the MOH AMI
message.  This assert catches the problem when the stasis message is
posted instead of by the thread processing the defective message.

* Always generate a backtrace when an ast_assert() fails.

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

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

main/channel.c
main/stasis_cache.c
main/utils.c
res/res_musiconhold.c

index b264a2170e902d81c6ed08b5566f4245b99d8ce7..23ea4b7c01bb6e3430de2da74cc015a70636ba68 100644 (file)
@@ -884,9 +884,8 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
        ast_channel_stage_snapshot(tmp);
 
        if (!(nativeformats = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_CACHE_STRINGS))) {
-               ao2_ref(tmp, -1);
                /* format capabilities structure allocation failure */
-               return NULL;
+               return ast_channel_unref(tmp);
        }
        ast_channel_nativeformats_set(tmp, nativeformats);
 
@@ -2263,10 +2262,16 @@ static void ast_channel_destructor(void *obj)
 
        /* Things that may possibly raise Stasis messages shouldn't occur after this point */
        ast_set_flag(ast_channel_flags(chan), AST_FLAG_DEAD);
-       ast_channel_lock(chan);
-       ast_channel_publish_snapshot(chan);
-       ast_channel_unlock(chan);
-       publish_cache_clear(chan);
+
+       if (ast_channel_internal_is_finalized(chan)) {
+               /* A channel snapshot should not be in the process of being staged now. */
+               ast_assert(!ast_test_flag(ast_channel_flags(chan), AST_FLAG_SNAPSHOT_STAGE));
+
+               ast_channel_lock(chan);
+               ast_channel_publish_snapshot(chan);
+               ast_channel_unlock(chan);
+               publish_cache_clear(chan);
+       }
 
        ast_channel_lock(chan);
 
index 12f49963c65e8b14f9c9c6a3c71abbb17f3a95e7..c1dab8539b767ad424d3a7ae15d359781023c98a 100644 (file)
@@ -343,10 +343,17 @@ struct stasis_message *stasis_cache_entry_get_remote(struct stasis_cache_entry *
 static struct stasis_cache_entry *cache_find(struct ao2_container *entries, struct stasis_message_type *type, const char *id)
 {
        struct cache_entry_key search_key;
+       struct stasis_cache_entry *entry;
 
        search_key.type = type;
        search_key.id = id;
-       return ao2_find(entries, &search_key, OBJ_SEARCH_KEY | OBJ_NOLOCK);
+       entry = ao2_find(entries, &search_key, OBJ_SEARCH_KEY | OBJ_NOLOCK);
+
+       /* Ensure that what we looked for is what we found. */
+       ast_assert(!entry
+               || (!strcmp(stasis_message_type_name(entry->key.type),
+                       stasis_message_type_name(type)) && !strcmp(entry->key.id, id)));
+       return entry;
 }
 
 /*!
index b1a95425c503a76cd317eb76bb8222c5132ea82c..6c022416a8cc35824c31eab7d439e7b31ff01e0f 100644 (file)
@@ -52,6 +52,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/sha1.h"
 #include "asterisk/cli.h"
 #include "asterisk/linkedlists.h"
+#include "asterisk/astobj2.h"
 
 #define AST_API_MODULE         /* ensure that inlinable API functions will be built in this module if required */
 #include "asterisk/strings.h"
@@ -2515,6 +2516,10 @@ void __ast_assert_failed(int condition, const char *condition_str, const char *f
                condition_str, condition);
        fprintf(stderr, "FRACK!, Failed assertion %s (%d) at line %d in %s of %s\n",
                condition_str, condition, line, function, file);
+
+       /* Generate a backtrace for the assert */
+       ao2_bt();
+
        /*
         * Give the logger a chance to get the message out, just in case
         * we abort(), or Asterisk crashes due to whatever problem just
index a94c4c4b7afd9fc1ef0cf0c9395b1d5295e51640..5bc63471cf91bd029045d2aa6a0e92ee3e38eca4 100644 (file)
@@ -280,6 +280,9 @@ static void moh_post_start(struct ast_channel *chan, const char *moh_class_name)
        message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan),
                ast_channel_moh_start_type(), json_object);
        if (message) {
+               /* A channel snapshot must have been in the cache. */
+               ast_assert(((struct ast_channel_blob *) stasis_message_data(message))->snapshot != NULL);
+
                stasis_publish(ast_channel_topic(chan), message);
        }
        ao2_cleanup(message);
@@ -295,6 +298,9 @@ static void moh_post_stop(struct ast_channel *chan)
        message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan),
                ast_channel_moh_stop_type(), NULL);
        if (message) {
+               /* A channel snapshot must have been in the cache. */
+               ast_assert(((struct ast_channel_blob *) stasis_message_data(message))->snapshot != NULL);
+
                stasis_publish(ast_channel_topic(chan), message);
        }
        ao2_cleanup(message);