aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b>2010-04-30 20:14:35 +0000
committermmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b>2010-04-30 20:14:35 +0000
commit2adaf4709e4f215b54ed4d9f1947975be29a8e2f (patch)
tree950a15116c92a568fd31033de91f6d0d5b957a0d
parent41eb20e5cc4745e9817ecba46ea161a236c476d0 (diff)
Merged revisions 260346 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk ................ r260346 | mmichelson | 2010-04-30 15:11:02 -0500 (Fri, 30 Apr 2010) | 24 lines Merged revisions 260345 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r260345 | mmichelson | 2010-04-30 15:08:15 -0500 (Fri, 30 Apr 2010) | 18 lines Fix potential crash from race condition due to accessing channel data without the channel locked. In res_musiconhold.c, there are several places where a channel's stream's existence is checked prior to calling ast_closestream on it. The issue here is that in several cases, the channel was not locked while checking the stream. The result was that if two threads checked the state of the channel's stream at approximately the same time, then there could be a situation where both threads attempt to call ast_closestream on the channel's stream. The result here is that the refcount for the stream would go below 0, resulting in a crash. I have added proper channel locking to res_musiconhold.c to ensure that we do not try to check chan->stream without the channel locked. A Digium customer has been using this patch for several weeks and has not had any crashes since applying the patch. ABE-2147 ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.0@260347 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--res/res_musiconhold.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c
index 03fa7762a..3eae2130c 100644
--- a/res/res_musiconhold.c
+++ b/res/res_musiconhold.c
@@ -306,7 +306,15 @@ static int moh_files_generator(struct ast_channel *chan, void *data, int len, in
state->sample_queue += samples;
while (state->sample_queue > 0) {
+ ast_channel_lock(chan);
if ((f = moh_files_readframe(chan))) {
+ /* We need to be sure that we unlock
+ * the channel prior to calling
+ * ast_write. Otherwise, the recursive locking
+ * that occurs can cause deadlocks when using
+ * indirect channels, like local channels
+ */
+ ast_channel_unlock(chan);
state->samples += f->samples;
state->sample_queue -= f->samples;
res = ast_write(chan, f);
@@ -315,8 +323,10 @@ static int moh_files_generator(struct ast_channel *chan, void *data, int len, in
ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
return -1;
}
- } else
+ } else {
+ ast_channel_unlock(chan);
return -1;
+ }
}
return res;
}
@@ -1406,16 +1416,17 @@ static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, con
static void local_ast_moh_stop(struct ast_channel *chan)
{
- struct moh_files_state *state = chan->music_state;
ast_clear_flag(chan, AST_FLAG_MOH);
ast_deactivate_generator(chan);
- if (state) {
+ ast_channel_lock(chan);
+ if (chan->music_state) {
if (chan->stream) {
ast_closestream(chan->stream);
chan->stream = NULL;
}
}
+ ast_channel_unlock(chan);
}
static void moh_class_destructor(void *obj)