diff options
author | jpeeler <jpeeler@f38db490-d61c-443f-a65b-d21fe96a405b> | 2009-09-15 15:59:45 +0000 |
---|---|---|
committer | jpeeler <jpeeler@f38db490-d61c-443f-a65b-d21fe96a405b> | 2009-09-15 15:59:45 +0000 |
commit | 2da41b2e63a51a940f4074d356e44e4c025be020 (patch) | |
tree | 4650b5080aee7595779097a500c0268d9630d42d /channels | |
parent | 89986aacaa2bfecc025ed44086741bc52e9a6bc0 (diff) |
Merged revisions 218430 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk
................
r218430 | jpeeler | 2009-09-14 17:38:25 -0500 (Mon, 14 Sep 2009) | 18 lines
Merged revisions 218401 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r218401 | jpeeler | 2009-09-14 16:47:11 -0500 (Mon, 14 Sep 2009) | 11 lines
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
........
................
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.2@218576 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_dahdi.c | 48 |
1 files changed, 24 insertions, 24 deletions
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 1ceb12927..b5609691e 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -1395,7 +1395,7 @@ static int dahdi_indicate(struct ast_channel *chan, int condition, const void *d static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan); static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen); static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len); -static int handle_init_event(struct dahdi_pvt *i, int event); +static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event); static const struct ast_channel_tech dahdi_tech = { .type = "DAHDI", @@ -9226,11 +9226,9 @@ static int dahdi_destroy_channel_bynum(int channel) return RESULT_FAILURE; } -/* returns < 0 = error, 0 event handled, >0 event handled and thread spawned */ -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; - int thread_spawned = 0; pthread_t threadid; struct ast_channel *chan; @@ -9285,8 +9283,6 @@ static int handle_init_event(struct dahdi_pvt *i, int event) if (res < 0) ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); ast_hangup(chan); - } else { - thread_spawned = 1; } } else ast_log(LOG_WARNING, "Unable to create channel\n"); @@ -9328,8 +9324,6 @@ static int handle_init_event(struct dahdi_pvt *i, int event) ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); } ast_hangup(chan); - } else { - thread_spawned = 1; } break; default: @@ -9337,7 +9331,7 @@ static int handle_init_event(struct dahdi_pvt *i, int event) 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: @@ -9402,7 +9396,7 @@ static int handle_init_event(struct dahdi_pvt *i, int event) 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; } if (i->sig & __DAHDI_SIG_FXO) { i->fxsoffhookstate = 0; @@ -9429,8 +9423,6 @@ static int handle_init_event(struct dahdi_pvt *i, int event) ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); - } else { - thread_spawned = 1; } } break; @@ -9440,12 +9432,11 @@ static int handle_init_event(struct dahdi_pvt *i, int event) "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; case DAHDI_EVENT_NEONMWI_ACTIVE: if (i->mwimonitor_neon) { notify_message(i->mailbox, 1); @@ -9459,7 +9450,7 @@ static int handle_init_event(struct dahdi_pvt *i, int event) } break; } - return thread_spawned; + return NULL; } static void *do_monitor(void *data) @@ -9467,6 +9458,7 @@ static void *do_monitor(void *data) 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]; @@ -9544,7 +9536,20 @@ static void *do_monitor(void *data) 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; @@ -9582,10 +9587,9 @@ static void *do_monitor(void *data) ast_debug(1, "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); @@ -9595,12 +9599,10 @@ static void *do_monitor(void *data) 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->mwimonitor_fsk && !i->mwisendactive) { ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd); - i = i->next; continue; } res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); @@ -9640,7 +9642,6 @@ static void *do_monitor(void *data) 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); @@ -9648,12 +9649,11 @@ static void *do_monitor(void *data) /* Don't hold iflock while handling init events */ ast_mutex_unlock(&iflock); if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) { - handle_init_event(i, res); + doomed = handle_init_event(i, res); } ast_mutex_lock(&iflock); } } - i=i->next; } ast_mutex_unlock(&iflock); } |