[asterisk-commits] mmichelson: trunk r105060 - in /trunk: ./ main/dial.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Feb 28 14:14:05 CST 2008
Author: mmichelson
Date: Thu Feb 28 14:14:04 2008
New Revision: 105060
URL: http://svn.digium.com/view/asterisk?view=rev&rev=105060
Log:
Merged revisions 104841 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r104841 | mmichelson | 2008-02-27 15:49:20 -0600 (Wed, 27 Feb 2008) | 17 lines
Two fixes:
1. Make the list of ast_dial_channels a lockable list. This is because in some cases,
the ast_dial may exist in multiple threads due to asynchronous execution of its application, and
I found some cases where race conditions could exist.
2. Check in ast_dial_join to be sure that the channel still exists before attempting to lock it, since
it could have gotten hung up but the is_running_app flag on the ast_dial_channel may not have been
cleared yet.
(closes issue #12038)
Reported by: jvandal
Patches:
12038v2.patch uploaded by putnopvut (license 60)
Tested by: jvandal
........
Modified:
trunk/ (props changed)
trunk/main/dial.c
Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.
Modified: trunk/main/dial.c
URL: http://svn.digium.com/view/asterisk/trunk/main/dial.c?view=diff&rev=105060&r1=105059&r2=105060
==============================================================================
--- trunk/main/dial.c (original)
+++ trunk/main/dial.c Thu Feb 28 14:14:04 2008
@@ -46,7 +46,7 @@
enum ast_dial_result state; /*!< Status of dial */
void *options[AST_DIAL_OPTION_MAX]; /*!< Global options */
ast_dial_state_callback state_callback; /*!< Status callback */
- AST_LIST_HEAD_NOLOCK(, ast_dial_channel) channels; /*!< Channels being dialed */
+ AST_LIST_HEAD(, ast_dial_channel) channels; /*!< Channels being dialed */
pthread_t thread; /*!< Thread (if running in async) */
ast_mutex_t lock; /*! Lock to protect the thread information above */
};
@@ -203,7 +203,7 @@
return NULL;
/* Initialize list of channels */
- AST_LIST_HEAD_INIT_NOLOCK(&dial->channels);
+ AST_LIST_HEAD_INIT(&dial->channels);
/* Initialize thread to NULL */
dial->thread = AST_PTHREADT_NULL;
@@ -312,6 +312,7 @@
int success = 0;
/* Iterate through channel list, requesting and calling each one */
+ AST_LIST_LOCK(&dial->channels);
AST_LIST_TRAVERSE(&dial->channels, channel, list) {
success += begin_dial_channel(channel, chan);
}
@@ -348,6 +349,7 @@
/* Update the dial channel with the new destination information */
channel->tech = ast_strdup(tech);
channel->device = ast_strdup(device);
+ AST_LIST_UNLOCK(&dial->channels);
/* Finally give it a go... send it out into the world */
begin_dial_channel(channel, chan);
@@ -363,10 +365,12 @@
{
struct ast_dial_channel *channel = NULL;
+ AST_LIST_LOCK(&dial->channels);
AST_LIST_TRAVERSE(&dial->channels, channel, list) {
if (channel->owner == owner)
break;
}
+ AST_LIST_UNLOCK(&dial->channels);
return channel;
}
@@ -386,8 +390,10 @@
switch (fr->subclass) {
case AST_CONTROL_ANSWER:
ast_verb(3, "%s answered %s\n", channel->owner->name, chan->name);
+ AST_LIST_LOCK(&dial->channels);
AST_LIST_REMOVE(&dial->channels, channel, list);
AST_LIST_INSERT_HEAD(&dial->channels, channel, list);
+ AST_LIST_UNLOCK(&dial->channels);
set_state(dial, AST_DIAL_RESULT_ANSWERED);
break;
case AST_CONTROL_BUSY:
@@ -453,8 +459,10 @@
switch (fr->subclass) {
case AST_CONTROL_ANSWER:
ast_verb(3, "%s answered\n", channel->owner->name);
+ AST_LIST_LOCK(&dial->channels);
AST_LIST_REMOVE(&dial->channels, channel, list);
AST_LIST_INSERT_HEAD(&dial->channels, channel, list);
+ AST_LIST_UNLOCK(&dial->channels);
set_state(dial, AST_DIAL_RESULT_ANSWERED);
break;
case AST_CONTROL_BUSY:
@@ -557,12 +565,14 @@
cs[pos++] = chan;
/* Add channels we are attempting to dial */
+ AST_LIST_LOCK(&dial->channels);
AST_LIST_TRAVERSE(&dial->channels, channel, list) {
if (channel->owner) {
cs[pos++] = channel->owner;
count++;
}
}
+ AST_LIST_UNLOCK(&dial->channels);
/* If we have no outbound channels in progress, switch state to unanswered and stop */
if (!count) {
@@ -624,6 +634,7 @@
/* Do post-processing from loop */
if (dial->state == AST_DIAL_RESULT_ANSWERED) {
/* Hangup everything except that which answered */
+ AST_LIST_LOCK(&dial->channels);
AST_LIST_TRAVERSE(&dial->channels, channel, list) {
if (!channel->owner || channel->owner == who)
continue;
@@ -632,6 +643,7 @@
ast_hangup(channel->owner);
channel->owner = NULL;
}
+ AST_LIST_UNLOCK(&dial->channels);
/* If ANSWER_EXEC is enabled as an option, execute application on answered channel */
if ((channel = find_relative_dial_channel(dial, who)) && (answer_exec = FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_ANSWER_EXEC))) {
channel->is_running_app = 1;
@@ -645,6 +657,7 @@
}
} else if (dial->state == AST_DIAL_RESULT_HANGUP) {
/* Hangup everything */
+ AST_LIST_LOCK(&dial->channels);
AST_LIST_TRAVERSE(&dial->channels, channel, list) {
if (!channel->owner)
continue;
@@ -653,6 +666,7 @@
ast_hangup(channel->owner);
channel->owner = NULL;
}
+ AST_LIST_UNLOCK(&dial->channels);
}
return dial->state;
@@ -771,15 +785,19 @@
dial->thread = AST_PTHREADT_STOP;
/* If the answered channel is running an application we have to soft hangup it, can't just poke the thread */
+ AST_LIST_LOCK(&dial->channels);
if (AST_LIST_FIRST(&dial->channels)->is_running_app) {
struct ast_channel *chan = AST_LIST_FIRST(&dial->channels)->owner;
- ast_channel_lock(chan);
- ast_softhangup(chan, AST_SOFTHANGUP_EXPLICIT);
- ast_channel_unlock(chan);
+ if (chan) {
+ ast_channel_lock(chan);
+ ast_softhangup(chan, AST_SOFTHANGUP_EXPLICIT);
+ ast_channel_unlock(chan);
+ }
} else {
/* Now we signal it with SIGURG so it will break out of it's waitfor */
pthread_kill(thread, SIGURG);
}
+ AST_LIST_UNLOCK(&dial->channels);
/* Yay done with it */
ast_mutex_unlock(&dial->lock);
@@ -804,12 +822,14 @@
if (!dial)
return;
+ AST_LIST_LOCK(&dial->channels);
AST_LIST_TRAVERSE(&dial->channels, channel, list) {
if (channel->owner) {
ast_hangup(channel->owner);
channel->owner = NULL;
}
}
+ AST_LIST_UNLOCK(&dial->channels);
return;
}
@@ -828,6 +848,7 @@
return -1;
/* Hangup and deallocate all the dialed channels */
+ AST_LIST_LOCK(&dial->channels);
AST_LIST_TRAVERSE_SAFE_BEGIN(&dial->channels, channel, list) {
/* Disable any enabled options */
for (i = 0; i < AST_DIAL_OPTION_MAX; i++) {
@@ -849,6 +870,7 @@
ast_free(channel);
}
AST_LIST_TRAVERSE_SAFE_END;
+ AST_LIST_UNLOCK(&dial->channels);
/* Disable any enabled options globally */
for (i = 0; i < AST_DIAL_OPTION_MAX; i++) {
@@ -900,10 +922,12 @@
return channel;
/* Hrm not at the end... looking through the list it is! */
+ AST_LIST_LOCK(&dial->channels);
AST_LIST_TRAVERSE(&dial->channels, channel, list) {
if (channel->num == num)
break;
}
+ AST_LIST_UNLOCK(&dial->channels);
return channel;
}
More information about the asterisk-commits
mailing list