[asterisk-commits] tilghman: trunk r233718 - /trunk/res/res_musiconhold.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Dec 8 12:22:50 CST 2009
Author: tilghman
Date: Tue Dec 8 12:22:44 2009
New Revision: 233718
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=233718
Log:
Find another ref leak and change how we manage module references.
(closes issue #16388)
Reported by: parisioa
Patches:
20091208__issue16388.diff.txt uploaded by tilghman (license 14)
Tested by: parisioa, tilghman
Review: https://reviewboard.asterisk.org/r/442/
Modified:
trunk/res/res_musiconhold.c
Modified: trunk/res/res_musiconhold.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_musiconhold.c?view=diff&rev=233718&r1=233717&r2=233718
==============================================================================
--- trunk/res/res_musiconhold.c (original)
+++ trunk/res/res_musiconhold.c Tue Dec 8 12:22:44 2009
@@ -212,8 +212,6 @@
};
static struct ao2_container *mohclasses;
-static struct ao2_container *deleted_classes;
-static pthread_t deleted_thread;
#define LOCAL_MPG_123 "/usr/local/bin/mpg123"
#define MPG_123 "/usr/bin/mpg123"
@@ -222,7 +220,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))) {
+ if (_ao2_ref_debug(dup, -1, (char *) tag, (char *) file, line, funcname) == 2) {
+ 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)
{
@@ -350,6 +373,7 @@
if (!chan->music_state && (state = ast_calloc(1, sizeof(*state)))) {
chan->music_state = state;
+ ast_module_ref(ast_module_info->self);
} else {
state = chan->music_state;
}
@@ -556,43 +580,6 @@
close(fds[1]);
}
return fds[0];
-}
-
-static void *deleted_monitor(void *data)
-{
- struct ao2_iterator iter;
- struct mohclass *class;
- struct ast_module *mod = NULL;
-
- for (;;) {
- pthread_testcancel();
- if (ao2_container_count(deleted_classes) == 0) {
- if (mod) {
- ast_module_unref(mod);
- mod = NULL;
- }
- poll(NULL, 0, -1);
- } else {
- /* While deleted classes are still in use, prohibit unloading */
- mod = ast_module_ref(ast_module_info->self);
- }
- pthread_testcancel();
- iter = ao2_iterator_init(deleted_classes, 0);
- while ((class = ao2_iterator_next(&iter))) {
- if (ao2_ref(class, 0) == 2) {
- ao2_unlink(deleted_classes, class);
- }
- ao2_ref(class, -1);
- }
- ao2_iterator_destroy(&iter);
- if (ao2_container_count(deleted_classes) == 0 && mod) {
- ast_module_unref(mod);
- mod = NULL;
- }
- pthread_testcancel();
- sleep(60);
- }
- return NULL;
}
static void *monmp3thread(void *data)
@@ -897,7 +884,8 @@
/* Initiating music_state for current channel. Channel should know name of moh class */
if (!chan->music_state && (state = ast_calloc(1, sizeof(*state)))) {
chan->music_state = state;
- state->class = class;
+ state->class = mohclass_ref(class, "Copying reference into state container");
+ ast_module_ref(ast_module_info->self);
} else
state = chan->music_state;
if (state && state->class != class) {
@@ -1182,19 +1170,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;
}
@@ -1217,6 +1211,8 @@
}
ast_free(chan->music_state);
chan->music_state = NULL;
+ /* Only held a module reference if we had a music state */
+ ast_module_unref(ast_module_info->self);
}
}
@@ -1566,12 +1562,7 @@
{
struct mohclass *class = obj;
- if (class->delete) {
- ao2_link(deleted_classes, obj);
- pthread_kill(deleted_thread, SIGURG);
- return CMP_MATCH;
- }
- return 0;
+ return class->delete ? CMP_MATCH : 0;
}
static int load_moh_classes(int reload)
@@ -1774,20 +1765,6 @@
}
}
ao2_iterator_destroy(&i);
- i = ao2_iterator_init(deleted_classes, 0);
- for (; (class = ao2_t_iterator_next(&i, "Show deleted classes iterator")); mohclass_unref(class, "Unref iterator in moh show classes")) {
- ast_cli(a->fd, "(Deleted) Class: %s (%d)\n", class->name, ao2_ref(class, 0) - 2);
- ast_cli(a->fd, "\tMode: %s\n", S_OR(class->mode, "<none>"));
- ast_cli(a->fd, "\tDirectory: %s\n", S_OR(class->dir, "<none>"));
- ast_cli(a->fd, "\tRealtime: %s\n", class->realtime ? "yes" : "no");
- if (ast_test_flag(class, MOH_CUSTOM)) {
- ast_cli(a->fd, "\tApplication: %s\n", S_OR(class->args, "<none>"));
- }
- if (strcasecmp(class->mode, "files")) {
- ast_cli(a->fd, "\tFormat: %s\n", ast_getformatname(class->format));
- }
- }
- ao2_iterator_destroy(&i);
return CLI_SUCCESS;
}
@@ -1819,14 +1796,6 @@
int res;
if (!(mohclasses = ao2_t_container_alloc(53, moh_class_hash, moh_class_cmp, "Moh class container"))) {
- return AST_MODULE_LOAD_DECLINE;
- }
-
- if (!(deleted_classes = ao2_t_container_alloc(53, moh_class_hash, moh_class_cmp, "Moh deleted class container"))) {
- return AST_MODULE_LOAD_DECLINE;
- }
-
- if (ast_pthread_create_background(&deleted_thread, NULL, deleted_monitor, NULL)) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -1898,10 +1867,6 @@
ast_cli_unregister_multiple(cli_moh, ARRAY_LEN(cli_moh));
ast_unregister_atexit(ast_moh_destroy);
- pthread_cancel(deleted_thread);
- pthread_kill(deleted_thread, SIGURG);
- pthread_join(deleted_thread, NULL);
-
return res;
}
More information about the asterisk-commits
mailing list