]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
fixes AUDIOHOOK_INHERIT regression
authorDavid Vossel <dvossel@digium.com>
Fri, 8 Jan 2010 19:39:30 +0000 (19:39 +0000)
committerDavid Vossel <dvossel@digium.com>
Fri, 8 Jan 2010 19:39:30 +0000 (19:39 +0000)
During the process of removing an audiohook from one channel
and attaching it to another the audiohook's status is updated
to DONE and then back to whatever it was previously.  Typically
updating the status after setting it to DONE is not a good idea
because DONE can trigger unrecoverable audiohook destruction
events... because of this a conditional check was added to
audiohook_update_status to explicitly prevent the audiohook
from ever changing after being set to DONE.  It was this check
that prevented audiohook inherit from work properly though.

Now ast_audiohook_move_by_source is treated as a special exception,
as the audiohook must be returned to its previous status after
attaching it to the new channel.  This is only a safe operation
because the audiohook's lock is held the entire time, otherwise
this could cause trouble.

(closes issue #16522)
Reported by: corruptor

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@238635 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/audiohook.h
main/audiohook.c

index bb81784dfef519471887b5e15adf5479a11b7d01..91081ce08fa1d08ec55cb32cb78f1d099cbb10a5 100644 (file)
@@ -205,6 +205,9 @@ struct ast_frame *ast_audiohook_write_list(struct ast_channel *chan, struct ast_
 /*! \brief Update audiohook's status
  * \param audiohook Audiohook structure
  * \param audiohook status enum
+ *
+ * \note once status is updated to DONE, this function can not be used to set the
+ * status back to any other setting.  Setting DONE effectively locks the status as such.
  */
 void ast_audiohook_update_status(struct ast_audiohook *audiohook, enum ast_audiohook_status status);
 
index 80b9f7f5e747d7a51c1de9aaf50adfe7952586f4..4a24a2fce554ad1a2b55d064e0bdb4831333f225 100644 (file)
@@ -361,7 +361,11 @@ int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audioho
 /*! \brief Update audiohook's status
  * \param audiohook status enum
  * \param audiohook Audiohook structure
+ *
+ * \note once status is updated to DONE, this function can not be used to set the
+ * status back to any other setting.  Setting DONE effectively locks the status as such.
  */
+
 void ast_audiohook_update_status(struct ast_audiohook *audiohook, enum ast_audiohook_status status)
 {
        ast_audiohook_lock(audiohook);
@@ -458,6 +462,7 @@ static struct ast_audiohook *find_audiohook_by_source(struct ast_audiohook_list
 void ast_audiohook_move_by_source(struct ast_channel *old_chan, struct ast_channel *new_chan, const char *source)
 {
        struct ast_audiohook *audiohook;
+       enum ast_audiohook_status oldstatus;
 
        if (!old_chan->audiohooks || !(audiohook = find_audiohook_by_source(old_chan->audiohooks, source))) {
                return;
@@ -466,11 +471,15 @@ void ast_audiohook_move_by_source(struct ast_channel *old_chan, struct ast_chann
        /* By locking both channels and the audiohook, we can assure that
         * another thread will not have a chance to read the audiohook's status
         * as done, even though ast_audiohook_remove signals the trigger
-        * condition
+        * condition.
         */
        ast_audiohook_lock(audiohook);
+       oldstatus = audiohook->status;
+
        ast_audiohook_remove(old_chan, audiohook);
        ast_audiohook_attach(new_chan, audiohook);
+
+       audiohook->status = oldstatus;
        ast_audiohook_unlock(audiohook);
 }