Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 182208) +++ channels/chan_sip.c (working copy) @@ -2940,6 +2940,9 @@ dialog->packets = dialog->packets->next; AST_SCHED_DEL(sched, cp->retransid); dialog_unref(cp->owner, "remove all current packets in this dialog, and the pointer to the dialog too as part of __sip_destroy"); + if (cp->data) { + ast_free(cp->data); + } ast_free(cp); } Index: res/res_musiconhold.c =================================================================== --- res/res_musiconhold.c (revision 182208) +++ res/res_musiconhold.c (working copy) @@ -213,14 +213,13 @@ } state->save_pos = state->pos; - - mohclass_unref(state->class); } static int ast_moh_files_next(struct ast_channel *chan) { struct moh_files_state *state = chan->music_state; int tries; + ao2_t_ref(state, +1, "Temporary pointer"); /* Discontinue a stream if it is running already */ if (chan->stream) { @@ -230,6 +229,7 @@ if (!state->class->total_files) { ast_log(LOG_WARNING, "No files available for class '%s'\n", state->class->name); + ao2_t_ref(state, -1, "Pointer out of scope"); return -1; } @@ -258,6 +258,7 @@ ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", state->class->filearray[state->pos], strerror(errno)); state->pos++; state->pos %= state->class->total_files; + ao2_t_ref(state, -1, "Pointer out of scope"); return -1; } @@ -269,13 +270,14 @@ if (state->samples) ast_seekstream(chan->stream, state->samples, SEEK_SET); + ao2_t_ref(state, -1, "Pointer out of scope"); return 0; } static struct ast_frame *moh_files_readframe(struct ast_channel *chan) { struct ast_frame *f = NULL; - + if (!(chan->stream && (f = ast_readframe(chan->stream)))) { if (!ast_moh_files_next(chan)) f = ast_readframe(chan->stream); @@ -290,6 +292,8 @@ struct ast_frame *f = NULL; int res = 0; + ao2_t_ref(state, +1, "Temporary pointer"); + state->sample_queue += samples; while (state->sample_queue > 0) { @@ -300,23 +304,38 @@ ast_frfree(f); if (res < 0) { ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno)); + ao2_t_ref(state, -1, "Pointer out of scope"); return -1; } - } else + } else { + ao2_t_ref(state, -1, "Pointer out of scope"); return -1; + } } + ao2_t_ref(state, -1, "Pointer out of scope"); return res; } +static void moh_state_destructor(void *obj) +{ + struct moh_files_state *state = obj; + struct mohclass *class = state->class; + state->class = NULL; + mohclass_unref(class); +} + static void *moh_files_alloc(struct ast_channel *chan, void *params) { struct moh_files_state *state; struct mohclass *class = params; - if (!chan->music_state && (state = ast_calloc(1, sizeof(*state)))) { + if (!chan->music_state && (state = ao2_alloc(sizeof(*state), moh_state_destructor))) { + ao2_t_ref(state, +1, "Duplicate pointer"); chan->music_state = state; } else { - state = chan->music_state; + if ((state = chan->music_state)) { + ao2_t_ref(chan->music_state, +1, "Temporary pointer"); + } } if (!state) { @@ -334,7 +353,8 @@ state->origwfmt = chan->writeformat; ast_verb(3, "Started music on hold, class '%s', on %s\n", class->name, chan->name); - + + ao2_t_ref(state, -1, "Pointer out of scope"); return chan->music_state; } @@ -799,14 +819,18 @@ struct moh_files_state *state; /* Initiating music_state for current channel. Channel should know name of moh class */ - if (!chan->music_state && (state = ast_calloc(1, sizeof(*state)))) { + if (!chan->music_state && (state = ao2_alloc(sizeof(*state), moh_state_destructor))) { + ao2_t_ref(state, +1, "Initializing state"); chan->music_state = state; - state->class = class; - } else + state->class = mohclass_ref(class); + } else { state = chan->music_state; + ao2_t_ref(state, +1, "Reclaiming state from channel"); + } if (state && state->class != class) { memset(state, 0, sizeof(*state)); - state->class = class; + ao2_t_ref(class, +1, "Setting state to point to class"); + state->class = mohclass_ref(class); } if ((res = mohalloc(class))) { @@ -818,6 +842,7 @@ } ast_verb(3, "Started music on hold, class '%s', on channel '%s'\n", class->name, chan->name); } + ao2_t_ref(state, -1, "Pointer loses scope"); return res; } @@ -1109,10 +1134,9 @@ static void local_ast_moh_cleanup(struct ast_channel *chan) { struct moh_files_state *state = chan->music_state; - if (state) { - ast_free(chan->music_state); chan->music_state = NULL; + ao2_t_ref(state, -1, "MOH cleanup"); } } @@ -1135,6 +1159,8 @@ struct moh_files_state *state = chan->music_state; int res; + ao2_t_ref(state, +1, "Duplicate pointer"); + /* The following is the order of preference for which class to use: * 1) The channels explicitly set musicclass, which should *only* be * set by a call to Set(CHANNEL(musicclass)=whatever) in the dialplan. @@ -1203,17 +1229,20 @@ } else { ast_log(LOG_WARNING, "A directory must be specified for class '%s'!\n", mohclass->name); mohclass = mohclass_unref(mohclass); + ao2_t_ref(state, -1, "Configuration error"); return -1; } } if (ast_strlen_zero(mohclass->mode)) { ast_log(LOG_WARNING, "A mode must be specified for class '%s'!\n", mohclass->name); mohclass = mohclass_unref(mohclass); + ao2_t_ref(state, -1, "Configuration error"); return -1; } if (ast_strlen_zero(mohclass->args) && !strcasecmp(mohclass->mode, "custom")) { ast_log(LOG_WARNING, "An application must be specified for class '%s'!\n", mohclass->name); mohclass = mohclass_unref(mohclass); + ao2_t_ref(state, -1, "Configuration error"); return -1; } @@ -1225,12 +1254,12 @@ if (state->class->realtime && !ast_test_flag(global_flags, MOH_CACHERTCLASSES) && !strcasecmp(mohclass->name, state->class->name)) { /* we found RT class with the same name, seems like we should continue playing existing one */ mohclass = mohclass_unref(mohclass); - mohclass = state->class; + mohclass = mohclass_ref(state->class); } } moh_register(mohclass, 0); } else { - /* We don't register RT moh class, so let's init it manualy */ + /* We don't register RT moh class, so let's init it manually */ time(&mohclass->start); mohclass->start -= respawn_time; @@ -1238,6 +1267,7 @@ if (!strcasecmp(mohclass->mode, "files")) { if (!moh_scan_files(mohclass)) { mohclass = mohclass_unref(mohclass); + ao2_t_ref(state, -1, "Configuration error"); return -1; } if (strchr(mohclass->args, 'r')) @@ -1274,7 +1304,7 @@ if (state->class->realtime && !ast_test_flag(global_flags, MOH_CACHERTCLASSES) && !strcasecmp(mohclass->name, state->class->name)) { /* we found RT class with the same name, seems like we should continue playing existing one */ mohclass = mohclass_unref(mohclass); - mohclass = state->class; + mohclass = mohclass_ref(state->class); } } else { if (ast_pthread_create_background(&mohclass->thread, NULL, monmp3thread, mohclass)) { @@ -1284,12 +1314,14 @@ mohclass->pseudofd = -1; } mohclass = mohclass_unref(mohclass); + ao2_t_ref(state, -1, "Configuration error"); return -1; } } } else { ast_log(LOG_WARNING, "Don't know how to do a mode '%s' music on hold\n", mohclass->mode); mohclass = mohclass_unref(mohclass); + ao2_t_ref(state, -1, "Configuration error"); return -1; } } @@ -1303,6 +1335,7 @@ } if (!mohclass) { + ao2_t_ref(state, -1, "Configuration error"); return -1; } @@ -1321,6 +1354,7 @@ } mohclass = mohclass_unref(mohclass); + ao2_t_ref(state, -1, "Pointer lost scope"); return res; }