[asterisk-commits] jpeeler: branch 1.4 r218401 - /branches/1.4/channels/chan_dahdi.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Sep 14 16:47:17 CDT 2009
Author: jpeeler
Date: Mon Sep 14 16:47:11 2009
New Revision: 218401
URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=218401
Log:
Fix handling of DAHDI_EVENT_REMOVED event to prevent crash in do_monitor.
After talking to rmudgett about some of his recent iflist locking changes, it
was determined that the only place that would destroy a channel without being
explicitly to do so was in handle_init_event. The loop to walk the interface
list has been modified to wait to destroy the channel until the dahdi_pvt of
the channel to be destroyed is no longer needed.
(closes issue #15378)
Reported by: samy
Modified:
branches/1.4/channels/chan_dahdi.c
Modified: branches/1.4/channels/chan_dahdi.c
URL: http://svn.asterisk.org/svn-view/asterisk/branches/1.4/channels/chan_dahdi.c?view=diff&rev=218401&r1=218400&r2=218401
==============================================================================
--- branches/1.4/channels/chan_dahdi.c (original)
+++ branches/1.4/channels/chan_dahdi.c Mon Sep 14 16:47:11 2009
@@ -7029,22 +7029,25 @@
struct dahdi_pvt *tmp = NULL;
struct dahdi_pvt *prev = NULL;
+ ast_mutex_lock(&iflock);
tmp = iflist;
while (tmp) {
if (tmp->channel == channel) {
int x = DAHDI_FLASH;
ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
destroy_channel(prev, tmp, 1);
+ ast_mutex_unlock(&iflock);
ast_module_unref(ast_module_info->self);
return RESULT_SUCCESS;
}
prev = tmp;
tmp = tmp->next;
}
+ ast_mutex_unlock(&iflock);
return RESULT_FAILURE;
}
-static int handle_init_event(struct dahdi_pvt *i, int event)
+static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
{
int res;
pthread_t threadid;
@@ -7143,7 +7146,7 @@
res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
if (res < 0)
ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
- return -1;
+ return NULL;
}
break;
case DAHDI_EVENT_NOALARM:
@@ -7209,7 +7212,7 @@
default:
ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
- return -1;
+ return NULL;
}
break;
case DAHDI_EVENT_POLARITY:
@@ -7241,15 +7244,14 @@
"interface %d\n", i->channel);
}
break;
- case DAHDI_EVENT_REMOVED: /* destroy channel */
+ case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
ast_log(LOG_NOTICE,
"Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
i->channel);
- dahdi_destroy_channel_bynum(i->channel);
- break;
+ return i;
}
pthread_attr_destroy(&attr);
- return 0;
+ return NULL;
}
static void *do_monitor(void *data)
@@ -7257,6 +7259,7 @@
int count, res, res2, spoint, pollres=0;
struct dahdi_pvt *i;
struct dahdi_pvt *last = NULL;
+ struct dahdi_pvt *doomed;
time_t thispass = 0, lastpass = 0;
int found;
char buf[1024];
@@ -7332,8 +7335,19 @@
spoint = 0;
lastpass = thispass;
thispass = time(NULL);
- i = iflist;
- while (i) {
+ doomed = NULL;
+ for (i = iflist;; i = i->next) {
+ if (doomed) {
+ int res;
+ res = dahdi_destroy_channel_bynum(doomed->channel);
+ if (!res) {
+ ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
+ }
+ doomed = NULL;
+ }
+ if (!i) {
+ break;
+ }
if (thispass != lastpass) {
if (!found && ((i == last) || ((i == iflist) && !last))) {
last = i;
@@ -7374,10 +7388,9 @@
ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
/* Don't hold iflock while handling init events */
ast_mutex_unlock(&iflock);
- handle_init_event(i, res);
+ doomed = handle_init_event(i, res);
ast_mutex_lock(&iflock);
}
- i = i->next;
continue;
}
pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
@@ -7387,12 +7400,10 @@
if (!i->pri)
#endif
ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
- i = i->next;
continue;
}
if (!i->cidspill) {
ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
- i = i->next;
continue;
}
res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
@@ -7423,7 +7434,6 @@
if (!i->pri)
#endif
ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
- i = i->next;
continue;
}
res = dahdi_get_event(i->subs[SUB_REAL].dfd);
@@ -7431,11 +7441,10 @@
ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
/* Don't hold iflock while handling init events */
ast_mutex_unlock(&iflock);
- handle_init_event(i, res);
+ doomed = handle_init_event(i, res);
ast_mutex_lock(&iflock);
}
}
- i=i->next;
}
ast_mutex_unlock(&iflock);
}
More information about the asterisk-commits
mailing list