diff --git a/apps/app_queue.c b/apps/app_queue.c index b0552a1096..8da75dedf8 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -4573,6 +4573,7 @@ static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struc /* No need to lock the channels because they are already locked in ast_do_masquerade */ if ((datastore = ast_channel_datastore_find(old_chan, &queue_transfer_info, NULL))) { ast_channel_datastore_remove(old_chan, datastore); + /* Datastore is freed in try_calling() */ } else { ast_log(LOG_WARNING, "Can't find the queue_transfer datastore.\n"); } @@ -5445,6 +5446,7 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce } if ((tds = ast_channel_datastore_find(qe->chan, &queue_transfer_info, NULL))) { ast_channel_datastore_remove(qe->chan, tds); + /* tds was added by setup_transfer_datastore() and is freed below. */ } ast_channel_unlock(qe->chan); update_queue(qe->parent, member, callcompletedinsl, (time(NULL) - callstart)); diff --git a/apps/app_speech_utils.c b/apps/app_speech_utils.c index 3785119f54..5b20819014 100644 --- a/apps/app_speech_utils.c +++ b/apps/app_speech_utils.c @@ -289,7 +289,9 @@ static struct ast_speech *find_speech(struct ast_channel *chan) return NULL; } + ast_channel_lock(chan); datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL); + ast_channel_unlock(chan); if (datastore == NULL) { return NULL; } @@ -298,6 +300,35 @@ static struct ast_speech *find_speech(struct ast_channel *chan) return speech; } +/*! + * \internal + * \brief Destroy the speech datastore on the given channel. + * + * \param chan Channel to destroy speech datastore. + * + * \retval 0 on success. + * \retval -1 not found. + */ +static int speech_datastore_destroy(struct ast_channel *chan) +{ + struct ast_datastore *datastore; + int res; + + ast_channel_lock(chan); + datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL); + if (datastore) { + ast_channel_datastore_remove(chan, datastore); + } + ast_channel_unlock(chan); + if (datastore) { + ast_datastore_free(datastore); + res = 0; + } else { + res = -1; + } + return res; +} + /* Helper function to find a specific speech recognition result by number and nbest alternative */ static struct ast_speech_result *find_result(struct ast_speech_result *results, char *result_num) { @@ -519,7 +550,9 @@ static int speech_create(struct ast_channel *chan, const char *data) } pbx_builtin_setvar_helper(chan, "ERROR", NULL); datastore->data = speech; + ast_channel_lock(chan); ast_channel_datastore_add(chan, datastore); + ast_channel_unlock(chan); return 0; } @@ -662,7 +695,6 @@ static int speech_background(struct ast_channel *chan, const char *data) int oldreadformat = AST_FORMAT_SLINEAR; char dtmf[AST_MAX_EXTENSION] = ""; struct timeval start = { 0, 0 }, current; - struct ast_datastore *datastore = NULL; char *parse, *filename_tmp = NULL, *filename = NULL, tmp[2] = "", dtmf_terminator = '#'; const char *tmp2 = NULL; struct ast_flags options = { 0 }; @@ -891,11 +923,7 @@ static int speech_background(struct ast_channel *chan, const char *data) /* See if it was because they hung up */ if (done == 3) { - /* Destroy speech structure */ - ast_speech_destroy(speech); - datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL); - if (datastore != NULL) - ast_channel_datastore_remove(chan, datastore); + speech_datastore_destroy(chan); } else { /* Channel is okay so restore read format */ ast_set_read_format(chan, oldreadformat); @@ -908,22 +936,10 @@ static int speech_background(struct ast_channel *chan, const char *data) /*! \brief SpeechDestroy() Dialplan Application */ static int speech_destroy(struct ast_channel *chan, const char *data) { - int res = 0; - struct ast_speech *speech = find_speech(chan); - struct ast_datastore *datastore = NULL; - - if (speech == NULL) + if (!chan) { return -1; - - /* Destroy speech structure */ - ast_speech_destroy(speech); - - datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL); - if (datastore != NULL) { - ast_channel_datastore_remove(chan, datastore); } - - return res; + return speech_datastore_destroy(chan); } static int unload_module(void) diff --git a/funcs/func_frame_trace.c b/funcs/func_frame_trace.c index 9b2785e322..c290058b34 100644 --- a/funcs/func_frame_trace.c +++ b/funcs/func_frame_trace.c @@ -185,6 +185,7 @@ static int frame_trace_helper(struct ast_channel *chan, const char *cmd, char *d id = datastore->data; ast_framehook_detach(chan, *id); ast_channel_datastore_remove(chan, datastore); + ast_datastore_free(datastore); } if (!(datastore = ast_datastore_alloc(&frame_trace_datastore, NULL))) {