diff options
-rw-r--r-- | channels/chan_dahdi.c | 49 | ||||
-rw-r--r-- | channels/sig_analog.c | 30 | ||||
-rw-r--r-- | channels/sig_analog.h | 3 |
3 files changed, 50 insertions, 32 deletions
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 1cc2539c1..187004ef8 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -2411,6 +2411,9 @@ static enum analog_event dahdievent_to_analogevent(int event) case DAHDI_EVENT_PULSE_START: res = ANALOG_EVENT_PULSE_START; break; + case DAHDI_EVENT_REMOVED: + res = ANALOG_EVENT_REMOVED; + break; case DAHDI_EVENT_NEONMWI_ACTIVE: res = ANALOG_EVENT_NEONMWI_ACTIVE; break; @@ -9916,8 +9919,7 @@ 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; @@ -10026,7 +10028,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: @@ -10083,7 +10085,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; } break; case DAHDI_EVENT_POLARITY: @@ -10118,12 +10120,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); @@ -10137,7 +10138,7 @@ static int handle_init_event(struct dahdi_pvt *i, int event) } break; } - return thread_spawned; + return NULL; } static void *do_monitor(void *data) @@ -10145,6 +10146,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]; @@ -10243,7 +10245,20 @@ static void *do_monitor(void *data) spoint = 0; lastpass = thispass; thispass = time(NULL); - for (i = iflist; i; i = i->next) { + 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; @@ -10283,9 +10298,9 @@ static void *do_monitor(void *data) /* Don't hold iflock while handling init events */ ast_mutex_unlock(&iflock); if (analog_lib_handles(i->sig, i->radio, i->oprmode)) - analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res)); + doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res)); else - handle_init_event(i, res); + doomed = handle_init_event(i, res); ast_mutex_lock(&iflock); } continue; @@ -10348,12 +10363,8 @@ static void *do_monitor(void *data) struct ast_channel *chan; ast_mutex_unlock(&iflock); if (analog_lib_handles(i->sig, i->radio, i->oprmode)) { - res = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID); - if (res) { - ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); - } else { - i->dtmfcid_holdoff_state = 1; - } + analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID); + i->dtmfcid_holdoff_state = 1; } else { chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0, NULL); if (!chan) { @@ -10392,9 +10403,9 @@ static void *do_monitor(void *data) ast_mutex_unlock(&iflock); if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) { if (analog_lib_handles(i->sig, i->radio, i->oprmode)) - analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res)); + doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res)); else - handle_init_event(i, res); + doomed = handle_init_event(i, res); } ast_mutex_lock(&iflock); } diff --git a/channels/sig_analog.c b/channels/sig_analog.c index e8127100a..ce3da7b60 100644 --- a/channels/sig_analog.c +++ b/channels/sig_analog.c @@ -256,6 +256,9 @@ static char *analog_event2str(enum analog_event event) case ANALOG_EVENT_PULSE_START: res = "ANALOG_EVENT_PULSE_START"; break; + case ANALOG_EVENT_REMOVED: + res = "ANALOG_EVENT_REMOVED"; + break; case ANALOG_EVENT_NEONMWI_ACTIVE: res = "ANALOG_EVENT_NEONMWI_ACTIVE"; break; @@ -3169,18 +3172,15 @@ struct ast_frame *analog_exception(struct analog_pvt *p, struct ast_channel *ast return f; } -int analog_handle_init_event(struct analog_pvt *i, int event) +void *analog_handle_init_event(struct analog_pvt *i, int event) { int res; pthread_t threadid; - pthread_attr_t attr; struct ast_channel *chan; ast_debug(1, "channel (%d) - signaling (%d) - event (%s)\n", i->channel, i->sig, analog_event2str(event)); - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); /* Handle an event on a given channel for the monitor thread. */ switch (event) { case ANALOG_EVENT_WINKFLASH: @@ -3223,7 +3223,8 @@ int analog_handle_init_event(struct analog_pvt *i, int event) } if (res < 0) ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); - if (ast_pthread_create(&threadid, &attr, __analog_ss_thread, i)) { + + if (ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, i)) { ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION); if (res < 0) { @@ -3262,7 +3263,7 @@ int analog_handle_init_event(struct analog_pvt *i, int event) chan = analog_new_ast_channel(i, AST_STATE_RING, 0, ANALOG_SUB_REAL, NULL); } i->ss_astchan = chan; - if (chan && ast_pthread_create(&threadid, &attr, __analog_ss_thread, i)) { + if (chan && ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, i)) { ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION); if (res < 0) { @@ -3279,7 +3280,7 @@ int analog_handle_init_event(struct analog_pvt *i, int event) if (res < 0) { ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); } - return -1; + return NULL; } break; case ANALOG_EVENT_NOALARM: @@ -3339,7 +3340,7 @@ int analog_handle_init_event(struct analog_pvt *i, int event) default: ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", analog_sigtype_to_str(i->sig), i->channel); res = analog_play_tone(i, ANALOG_SUB_REAL, -1); - return -1; + return NULL; } break; case ANALOG_EVENT_POLARITY: @@ -3362,7 +3363,7 @@ int analog_handle_init_event(struct analog_pvt *i, int event) i->channel); chan = analog_new_ast_channel(i, AST_STATE_PRERING, 0, ANALOG_SUB_REAL, NULL); i->ss_astchan = chan; - if (chan && ast_pthread_create(&threadid, &attr, __analog_ss_thread, i)) { + if (chan && ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, i)) { ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); } } @@ -3383,7 +3384,7 @@ int analog_handle_init_event(struct analog_pvt *i, int event) i->channel); chan = analog_new_ast_channel(i, AST_STATE_PRERING, 0, ANALOG_SUB_REAL, NULL); i->ss_astchan = chan; - if (chan && ast_pthread_create(&threadid, &attr, __analog_ss_thread, i)) { + if (chan && ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, i)) { ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); } } @@ -3394,6 +3395,12 @@ int analog_handle_init_event(struct analog_pvt *i, int event) "interface %d\n", i->channel); } break; + case ANALOG_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); + return i->chan_pvt; + break; case ANALOG_EVENT_NEONMWI_ACTIVE: analog_handle_notify_message(NULL, i, -1, ANALOG_EVENT_NEONMWI_ACTIVE); break; @@ -3401,8 +3408,7 @@ int analog_handle_init_event(struct analog_pvt *i, int event) analog_handle_notify_message(NULL, i, -1, ANALOG_EVENT_NEONMWI_INACTIVE); break; } - pthread_attr_destroy(&attr); - return 0; + return NULL; } diff --git a/channels/sig_analog.h b/channels/sig_analog.h index 522012b26..de86662df 100644 --- a/channels/sig_analog.h +++ b/channels/sig_analog.h @@ -78,6 +78,7 @@ enum analog_event { ANALOG_EVENT_RINGBEGIN, ANALOG_EVENT_PULSE_START, ANALOG_EVENT_ERROR, + ANALOG_EVENT_REMOVED, ANALOG_EVENT_NEONMWI_ACTIVE, ANALOG_EVENT_NEONMWI_INACTIVE, ANALOG_EVENT_DTMFCID, @@ -328,7 +329,7 @@ struct ast_channel * analog_request(struct analog_pvt *p, int *callwait, const s int analog_available(struct analog_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched); -int analog_handle_init_event(struct analog_pvt *i, int event); +void *analog_handle_init_event(struct analog_pvt *i, int event); int analog_config_complete(struct analog_pvt *p); |