From: Brent Eagles Date: Tue, 13 Nov 2012 18:10:22 +0000 (+0000) Subject: Patch to prevent stopping the active generator when it is not the silence X-Git-Tag: 1.8.20.0-rc1~38 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=68ae2318a156d70c31464d86f861ca0c245810d6;p=thirdparty%2Fasterisk.git Patch to prevent stopping the active generator when it is not the silence generator. This patch introduces an internal helper function to safely check whether the current generator is the one that is expected before deactivating it. The current externally accessible ast_channel_stop_generator() function has been modified to be implemented in terms of the new function. (closes issue ASTERISK-19918) Reported by: Eduardo Abad git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@376199 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/main/channel.c b/main/channel.c index a6ec4ce4a8..ae208dc8b3 100644 --- a/main/channel.c +++ b/main/channel.c @@ -3118,7 +3118,11 @@ static int generator_force(const void *data) res = generate(chan, tmp, 0, ast_format_rate(chan->writeformat & AST_FORMAT_AUDIO_MASK) / 50); - chan->generatordata = tmp; + ast_channel_lock(chan); + if (chan->generator && generate == chan->generator->generate) { + chan->generatordata = tmp; + } + ast_channel_unlock(chan); if (res) { ast_debug(1, "Auto-deactivating generator\n"); @@ -8222,18 +8226,46 @@ struct ast_silence_generator *ast_channel_start_silence_generator(struct ast_cha return state; } +static int internal_deactivate_generator(struct ast_channel *chan, void* generator) +{ + ast_channel_lock(chan); + + if (!chan->generatordata) { + ast_debug(1, "Trying to stop silence generator when there is no " + "generator on '%s'\n", chan->name); + ast_channel_unlock(chan); + return 0; + } + if (chan->generator != generator) { + ast_debug(1, "Trying to stop silence generator when it is not the current " + "generator on '%s'\n", chan->name); + ast_channel_unlock(chan); + return 0; + } + if (chan->generator && chan->generator->release) { + chan->generator->release(chan, chan->generatordata); + } + chan->generatordata = NULL; + chan->generator = NULL; + ast_channel_set_fd(chan, AST_GENERATOR_FD, -1); + ast_clear_flag(chan, AST_FLAG_WRITE_INT); + ast_settimeout(chan, 0, NULL, NULL); + ast_channel_unlock(chan); + + return 1; +} + void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state) { if (!state) return; - ast_deactivate_generator(chan); - - ast_debug(1, "Stopped silence generator on '%s'\n", chan->name); - - if (ast_set_write_format(chan, state->old_write_format) < 0) - ast_log(LOG_ERROR, "Could not return write format to its original state\n"); + if (internal_deactivate_generator(chan, &silence_generator)) { + ast_debug(1, "Stopped silence generator on '%s'\n", chan->name); + if (ast_set_write_format(chan, state->old_write_format) < 0) + ast_log(LOG_ERROR, "Could not return write format to its original state\n"); + } ast_free(state); }