diff options
author | lmadsen <lmadsen@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-05-03 15:25:09 +0000 |
---|---|---|
committer | lmadsen <lmadsen@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-05-03 15:25:09 +0000 |
commit | 9f3c1ad6d1c33077f2db07755ba7c51dccc6ecb9 (patch) | |
tree | 64ed37bcfd76f92757a769cb02103b29a6b50d64 | |
parent | 1a5a1ddf50b61e638a8db5217ea072039e83f992 (diff) | |
parent | 90fcc2c35ba4abb6432ee2f9472cdcba8e88f44f (diff) |
Create Asterisk 1.6.0.27 release from 1.6.0.27-rc3.
git-svn-id: http://svn.digium.com/svn/asterisk/tags/1.6.0.27@260607 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r-- | .version | 2 | ||||
-rw-r--r-- | ChangeLog | 20 | ||||
-rw-r--r-- | channels/chan_local.c | 19 | ||||
-rw-r--r-- | include/asterisk/audiohook.h | 13 | ||||
-rw-r--r-- | main/audiohook.c | 45 | ||||
-rw-r--r-- | main/channel.c | 7 |
6 files changed, 81 insertions, 25 deletions
@@ -1 +1 @@ -1.6.0.27-rc2 +1.6.0.27-rc3 @@ -1,3 +1,23 @@ +2010-04-29 Leif Madsen <lmadsen@digium.com> + + * Astersik 1.6.0.27-rc3 Released + +2010-04-29 10:31 +0000 [r260053] David Vossel <dvossel@digium.com> + + * include/asterisk/audiohook.h, main/audiohook.c: Fixes crash in + audiohook_write_list. (closes issue 0017052) Reported by: dvossel + Tested by: dvossel. (closes issue 0016196) Reported by: atis. + Review: https://reviewboard.asterisk.org/r/623/ + +2010-04-28 10:31 +0000 [r259936] David Vossel <dvossel@digium.com> + + * channels/chan_local.c, main/channel.c: Resolves deadlocks in + chan_local. (closes issue 0017185) Reported by: schmoozecom + Patches: issue_17185_v1.diff uploaded by dvossel (license 671) + issue_17185_v2.diff uploaded by dvossel (license 671) Tested + by: schmoozecom, GameGamer43 + Review: https://reviewboard.asterisk.org/r/631/ + 2010-04-13 Leif Madsen <lmadsen@digium.com> * Asterisk 1.6.0.27-rc2 Released diff --git a/channels/chan_local.c b/channels/chan_local.c index 138ded848..11cde5aad 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -540,12 +540,12 @@ static int local_hangup(struct ast_channel *ast) /* Deadlock avoidance */ while (p->owner && ast_channel_trylock(p->owner)) { ast_mutex_unlock(&p->lock); - if (ast) { - ast_channel_unlock(ast); + if (p->chan) { + ast_channel_unlock(p->chan); } usleep(1); - if (ast) { - ast_channel_lock(ast); + if (p->chan) { + ast_channel_lock(p->chan); } ast_mutex_lock(&p->lock); } @@ -560,8 +560,17 @@ static int local_hangup(struct ast_channel *ast) } else { ast_module_user_remove(p->u_owner); while (p->chan && ast_channel_trylock(p->chan)) { - DEADLOCK_AVOIDANCE(&p->lock); + ast_mutex_unlock(&p->lock); + if (p->owner) { + ast_channel_unlock(p->owner); + } + usleep(1); + if (p->owner) { + ast_channel_lock(p->owner); + } + ast_mutex_lock(&p->lock); } + p->owner = NULL; if (p->chan) { ast_queue_hangup(p->chan); diff --git a/include/asterisk/audiohook.h b/include/asterisk/audiohook.h index 0a36bb934..dc6c3e1f3 100644 --- a/include/asterisk/audiohook.h +++ b/include/asterisk/audiohook.h @@ -73,9 +73,16 @@ struct ast_audiohook; * \param chan Channel * \param frame Frame of audio to manipulate * \param direction Direction frame came from - * \return Returns 0 on success, -1 on failure - * \note An audiohook does not have any reference to a private data structure for manipulate types. It is up to the manipulate callback to store this data - * via it's own method. An example would be datastores. + * \return Returns 0 on success, -1 on failure. + * \note An audiohook does not have any reference to a private data structure for manipulate + * types. It is up to the manipulate callback to store this data via it's own method. + * An example would be datastores. + * \note The input frame should never be freed or corrupted during a manipulate callback. + * If the callback has the potential to corrupt the frame's data during manipulation, + * local data should be used for the manipulation and only copied to the frame on + * success. + * \note A failure return value indicates that the frame was not manipulated and that + * is being returned in its original state. */ typedef int (*ast_audiohook_manipulate_callback)(struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction); diff --git a/main/audiohook.c b/main/audiohook.c index 7e7f87785..5f4f02520 100644 --- a/main/audiohook.c +++ b/main/audiohook.c @@ -572,7 +572,29 @@ static struct ast_frame *dtmf_audiohook_write_list(struct ast_channel *chan, str return frame; } -/*! \brief Pass an AUDIO frame off to be handled by the audiohook core +/*! + * \brief Pass an AUDIO frame off to be handled by the audiohook core + * + * \details + * This function has 3 ast_frames and 3 parts to handle each. At the beginning of this + * function all 3 frames, start_frame, middle_frame, and end_frame point to the initial + * input frame. + * + * Part_1: Translate the start_frame into SLINEAR audio if it is not already in that + * format. The result of this part is middle_frame is guaranteed to be in + * SLINEAR format for Part_2. + * Part_2: Send middle_frame off to spies and manipulators. At this point middle_frame is + * either a new frame as result of the translation, or points directly to the start_frame + * because no translation to SLINEAR audio was required. The result of this part + * is end_frame will be updated to point to middle_frame if any audiohook manipulation + * took place. + * Part_3: Translate end_frame's audio back into the format of start frame if necessary. + * At this point if middle_frame != end_frame, we are guaranteed that no manipulation + * took place and middle_frame can be freed as it was translated... If middle_frame was + * not translated and still pointed to start_frame, it would be equal to end_frame as well + * regardless if manipulation took place which would not result in this free. The result + * of this part is end_frame is guaranteed to be the format of start_frame for the return. + * * \param chan Channel that the list is coming off of * \param audiohook_list List of audiohooks * \param direction Direction frame is coming in from @@ -587,6 +609,7 @@ static struct ast_frame *audio_audiohook_write_list(struct ast_channel *chan, st struct ast_audiohook *audiohook = NULL; int samples = frame->samples; + /* ---Part_1. translate start_frame to SLINEAR if necessary. */ /* If the frame coming in is not signed linear we have to send it through the in_translate path */ if (frame->subclass != AST_FORMAT_SLINEAR) { if (in_translate->format != frame->subclass) { @@ -601,6 +624,7 @@ static struct ast_frame *audio_audiohook_write_list(struct ast_channel *chan, st samples = middle_frame->samples; } + /* ---Part_2: Send middle_frame to spy and manipulator lists. middle_frame is guaranteed to be SLINEAR here.*/ /* Queue up signed linear frame to each spy */ AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->spy_list, audiohook, list) { ast_audiohook_lock(audiohook); @@ -654,20 +678,21 @@ static struct ast_frame *audio_audiohook_write_list(struct ast_channel *chan, st audiohook->manipulate_callback(audiohook, chan, NULL, direction); continue; } - /* Feed in frame to manipulation */ + /* Feed in frame to manipulation. */ if (audiohook->manipulate_callback(audiohook, chan, middle_frame, direction)) { - ast_frfree(middle_frame); - middle_frame = NULL; + /* XXX IGNORE FAILURE */ + + /* If the manipulation fails then the frame will be returned in its original state. + * Since there are potentially more manipulator callbacks in the list, no action should + * be taken here to exit early. */ } ast_audiohook_unlock(audiohook); } AST_LIST_TRAVERSE_SAFE_END - if (middle_frame) { - end_frame = middle_frame; - } + end_frame = middle_frame; } - /* Now we figure out what to do with our end frame (whether to transcode or not) */ + /* ---Part_3: Decide what to do with the end_frame (whether to transcode or not) */ if (middle_frame == end_frame) { /* Middle frame was modified and became the end frame... let's see if we need to transcode */ if (end_frame->subclass != start_frame->subclass) { @@ -692,9 +717,7 @@ static struct ast_frame *audio_audiohook_write_list(struct ast_channel *chan, st } } else { /* No frame was modified, we can just drop our middle frame and pass the frame we got in out */ - if (middle_frame) { - ast_frfree(middle_frame); - } + ast_frfree(middle_frame); } return end_frame; diff --git a/main/channel.c b/main/channel.c index d9b0173c5..e9f7f4359 100644 --- a/main/channel.c +++ b/main/channel.c @@ -1986,25 +1986,22 @@ int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, int res = 0; ast_channel_lock(chan); - if (chan->generatordata) { if (chan->generator && chan->generator->release) chan->generator->release(chan, chan->generatordata); chan->generatordata = NULL; } - - ast_prod(chan); if (gen->alloc && !(chan->generatordata = gen->alloc(chan, params))) { res = -1; } - if (!res) { ast_settimeout(chan, 160, generator_force, chan); chan->generator = gen; } - ast_channel_unlock(chan); + ast_prod(chan); + return res; } |