Index: res/res_musiconhold.c =================================================================== --- res/res_musiconhold.c (revision 232854) +++ res/res_musiconhold.c (working copy) @@ -50,6 +50,8 @@ #include #endif +#define REF_DEBUG + #include "asterisk/lock.h" #include "asterisk/file.h" #include "asterisk/channel.h" @@ -195,7 +197,32 @@ static int reload(void); #define mohclass_ref(class,string) (ao2_t_ref((class), +1, (string)), class) + +#ifndef REF_DEBUG #define mohclass_unref(class,string) (ao2_t_ref((class), -1, (string)), (struct mohclass *) NULL) +#else +#define mohclass_unref(class,string) _mohclass_unref(class, string, __FILE__,__LINE__,__PRETTY_FUNCTION__) +static struct mohclass *_mohclass_unref(struct mohclass *class, const char *tag, const char *file, int line, const char *funcname) +{ + struct mohclass *dup; + if ((dup = ao2_find(mohclasses, class, OBJ_POINTER)) || (dup = ao2_find(deleted_classes, class, OBJ_POINTER))) { + if (_ao2_ref_debug(dup, -1, (char *) tag, (char *) file, line, funcname) == 1) { + FILE *ref = fopen("/tmp/refs", "a"); + if (ref) { + fprintf(ref, "%p =1 %s:%d:%s (%s) BAD ATTEMPT!\n", class, file, line, funcname, tag); + fclose(ref); + } + ast_log(LOG_WARNING, "Attempt to unref mohclass %p (%s) when only 1 ref remained, and class is still in a container! (at %s:%d (%s))\n", + class, class->name, file, line, funcname); + } else { + ao2_ref(class, -1); + } + } else { + ao2_t_ref(class, -1, (char *) tag); + } + return NULL; +} +#endif static void moh_files_release(struct ast_channel *chan, void *data) { @@ -1146,19 +1173,25 @@ if (!strcasecmp(moh->mode, "files")) { if (init_files_class(moh)) { - moh = mohclass_unref(moh, "unreffing potential new moh class (init_files_class failed)"); + if (unref) { + moh = mohclass_unref(moh, "unreffing potential new moh class (init_files_class failed)"); + } return -1; } } else if (!strcasecmp(moh->mode, "mp3") || !strcasecmp(moh->mode, "mp3nb") || !strcasecmp(moh->mode, "quietmp3") || !strcasecmp(moh->mode, "quietmp3nb") || !strcasecmp(moh->mode, "httpmp3") || !strcasecmp(moh->mode, "custom")) { if (init_app_class(moh)) { - moh = mohclass_unref(moh, "unreffing potential new moh class (init_app_class_failed)"); + if (unref) { + moh = mohclass_unref(moh, "unreffing potential new moh class (init_app_class_failed)"); + } return -1; } } else { ast_log(LOG_WARNING, "Don't know how to do a mode '%s' music on hold\n", moh->mode); - moh = mohclass_unref(moh, "unreffing potential new moh class (unknown mode)"); + if (unref) { + moh = mohclass_unref(moh, "unreffing potential new moh class (unknown mode)"); + } return -1; }