diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 1f51f883f0..4d368123d8 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -240,6 +240,11 @@ AST_MUTEX_DEFINE_STATIC(monlock); /*! \brief This is the thread for the monitor which checks for input on the channels which are not currently in use. */ static pthread_t monitor_thread = AST_PTHREADT_NULL; +static ast_cond_t ss_thread_complete = PTHREAD_COND_INITIALIZER; +static ast_mutex_t ss_thread_lock = { PTHREAD_MUTEX_INITIALIZER }; +static ast_mutex_t restart_lock = { PTHREAD_MUTEX_INITIALIZER }; +static int ss_thread_count = 0; +static int num_restart_pending = 0; static int restart_monitor(void); @@ -468,6 +473,7 @@ static struct dahdi_pvt { unsigned int priexclusive:1; unsigned int pulse:1; unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */ + unsigned int restartpending:1; /*!< flag to ensure counted only once for restart */ unsigned int restrictcid:1; /*!< Whether restrict the callerid -> only send ANI */ unsigned int threewaycalling:1; unsigned int transfer:1; @@ -746,7 +752,8 @@ static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri) } } while (res); /* Then break the poll */ - pthread_kill(pri->master, SIGURG); + if (pri->master != AST_PTHREADT_NULL) + pthread_kill(pri->master, SIGURG); return 0; } #endif @@ -782,11 +789,11 @@ static int cidrings[NUM_CADENCE_MAX] = { static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok) { int res; - if (p->subs[0].owner == ast) + if (p->subs[SUB_REAL].owner == ast) res = 0; - else if (p->subs[1].owner == ast) + else if (p->subs[SUB_CALLWAIT].owner == ast) res = 1; - else if (p->subs[2].owner == ast) + else if (p->subs[SUB_THREEWAY].owner == ast) res = 2; else { res = -1; @@ -1644,7 +1651,8 @@ static inline int dahdi_set_hook(int fd, int hs) if (res < 0) { if (errno == EINPROGRESS) return 0; - ast_log(LOG_WARNING, "dahdi hook failed: %s\n", strerror(errno)); + ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); + /* will expectedly fail if phone is off hook during operation, such as during a restart */ } return res; @@ -2248,6 +2256,8 @@ static void destroy_dahdi_pvt(struct dahdi_pvt **pvt) if (p->use_smdi) ast_smdi_interface_unref(p->smdi_iface); ast_mutex_destroy(&p->lock); + if (p->owner) + p->owner->tech_pvt = NULL; free(p); *pvt = NULL; } @@ -2308,6 +2318,39 @@ static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int no return 0; } +static void destroy_all_channels(void) +{ + int x; + struct dahdi_pvt *p, *pl; + + while (num_restart_pending) { + usleep(1); + } + + ast_mutex_lock(&iflock); + /* Destroy all the interfaces and free their memory */ + p = iflist; + while (p) { + /* Free any callerid */ + if (p->cidspill) + ast_free(p->cidspill); + /* Close the DAHDI thingy */ + if (p->subs[SUB_REAL].dfd > -1) + dahdi_close(p->subs[SUB_REAL].dfd); + pl = p; + p = p->next; + x = pl->channel; + /* Free associated memory */ + if (pl) + destroy_dahdi_pvt(&pl); + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x); + } + iflist = NULL; + ifcount = 0; + ast_mutex_unlock(&iflock); +} + #ifdef HAVE_PRI static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility"; static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility"; @@ -2750,7 +2793,8 @@ static int dahdi_hangup(struct ast_channel *ast) p->pri = NULL; } #endif - restart_monitor(); + if (num_restart_pending == 0) + restart_monitor(); } p->callwaitingrepeat = 0; @@ -2763,6 +2807,11 @@ static int dahdi_hangup(struct ast_channel *ast) ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name); ast_mutex_lock(&iflock); + + if (p->restartpending) { + num_restart_pending--; + } + tmp = iflist; prev = NULL; if (p->destroy) { @@ -5497,22 +5546,22 @@ static void *ss_thread(void *data) int res; int index; + ss_thread_count++; /* in the bizarre case where the channel has become a zombie before we even get started here, abort safely */ if (!p) { ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); ast_hangup(chan); - return NULL; + goto quit; } - if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name); index = dahdi_get_index(chan, p, 1); if (index < 0) { ast_log(LOG_WARNING, "Huh?\n"); ast_hangup(chan); - return NULL; + goto quit; } if (p->dsp) ast_dsp_digitreset(p->dsp); @@ -5536,7 +5585,7 @@ static void *ss_thread(void *data) if (res < 0) { ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); ast_hangup(chan); - return NULL; + goto quit; } else if (res) { exten[len++] = res; exten[len] = '\0'; @@ -5569,7 +5618,7 @@ static void *ss_thread(void *data) /* Since we send release complete here, we won't get one */ p->call = NULL; } - return NULL; + goto quit; break; #endif case SIG_FEATD: @@ -5584,7 +5633,7 @@ static void *ss_thread(void *data) case SIG_SF_FEATB: case SIG_SFWINK: if (dahdi_wink(p, index)) - return NULL; + goto quit; /* Fall through */ case SIG_EM: case SIG_EM_E1: @@ -5621,7 +5670,7 @@ static void *ss_thread(void *data) case SIG_FEATDMF_TA: res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); - if (dahdi_wink(p, index)) return NULL; + if (dahdi_wink(p, index)) goto quit; dtmfbuf[0] = 0; /* Wait for the first digit (up to 5 seconds). */ res = ast_waitfordigit(chan, 5000); @@ -5636,7 +5685,7 @@ static void *ss_thread(void *data) /* if international caca, do it again to get real ANO */ if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) { - if (dahdi_wink(p, index)) return NULL; + if (dahdi_wink(p, index)) goto quit; dtmfbuf[0] = 0; /* Wait for the first digit (up to 5 seconds). */ res = ast_waitfordigit(chan, 5000); @@ -5683,7 +5732,7 @@ static void *ss_thread(void *data) if (res < 0) { ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); ast_hangup(chan); - return NULL; + goto quit; } else if (res) { dtmfbuf[len++] = res; dtmfbuf[len] = '\0'; @@ -5697,11 +5746,11 @@ static void *ss_thread(void *data) if (res == -1) { ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); ast_hangup(chan); - return NULL; + goto quit; } else if (res < 0) { ast_log(LOG_DEBUG, "Got hung up before digits finished\n"); ast_hangup(chan); - return NULL; + goto quit; } if (p->sig == SIG_FGC_CAMA) { @@ -5709,7 +5758,7 @@ static void *ss_thread(void *data) if (ast_safe_sleep(chan,1000) == -1) { ast_hangup(chan); - return NULL; + goto quit; } dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); @@ -5798,7 +5847,7 @@ static void *ss_thread(void *data) /* some switches require a minimum guard time between the last FGD wink and something that answers immediately. This ensures it */ - if (ast_safe_sleep(chan,100)) return NULL; + if (ast_safe_sleep(chan,100)) goto quit; } dahdi_enable_ec(p); if (NEED_MFDETECT(p)) { @@ -5820,7 +5869,7 @@ static void *ss_thread(void *data) ast_log(LOG_WARNING, "PBX exited non-zero\n"); res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); } - return NULL; + goto quit; } else { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); @@ -5835,7 +5884,7 @@ static void *ss_thread(void *data) ast_waitstream(chan, ""); res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); ast_hangup(chan); - return NULL; + goto quit; } break; case SIG_FXOLS: @@ -5859,7 +5908,7 @@ static void *ss_thread(void *data) ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); res = tone_zone_play_tone(p->subs[index].dfd, -1); ast_hangup(chan); - return NULL; + goto quit; } else if (res) { exten[len++]=res; exten[len] = '\0'; @@ -5905,7 +5954,7 @@ static void *ss_thread(void *data) ast_log(LOG_WARNING, "PBX exited non-zero\n"); res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); } - return NULL; + goto quit; } } else { /* It's a match, but they just typed a digit, and there is an ambiguous match, @@ -5917,7 +5966,7 @@ static void *ss_thread(void *data) res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); dahdi_wait_event(p->subs[index].dfd); ast_hangup(chan); - return NULL; + goto quit; } else if (p->callwaiting && !strcmp(exten, "*70")) { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name); @@ -5954,11 +6003,11 @@ static void *ss_thread(void *data) dahdi_wait_event(p->subs[index].dfd); } ast_hangup(chan); - return NULL; + goto quit; } else { ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); ast_hangup(chan); - return NULL; + goto quit; } } else if (!p->hidecallerid && !strcmp(exten, "*67")) { @@ -6088,7 +6137,7 @@ static void *ss_thread(void *data) if (ast_bridged_channel(p->subs[SUB_REAL].owner)) ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); ast_hangup(chan); - return NULL; + goto quit; } else { tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); dahdi_wait_event(p->subs[index].dfd); @@ -6097,7 +6146,7 @@ static void *ss_thread(void *data) unalloc_sub(p, SUB_THREEWAY); p->owner = p->subs[SUB_REAL].owner; ast_hangup(chan); - return NULL; + goto quit; } } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && ((exten[0] != '*') || (strlen(exten) > 2))) { @@ -6130,7 +6179,7 @@ static void *ss_thread(void *data) if (!f) { ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n"); ast_hangup(chan); - return NULL; + goto quit; } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) { res = 1; } else @@ -6185,7 +6234,7 @@ static void *ss_thread(void *data) ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " "Exiting simple switch\n"); ast_hangup(chan); - return NULL; + goto quit; } f = ast_read(chan); if (!f) @@ -6230,7 +6279,7 @@ static void *ss_thread(void *data) ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); callerid_free(cs); ast_hangup(chan); - return NULL; + goto quit; } if (i & DAHDI_IOMUX_SIGEVENT) { res = dahdi_get_event(p->subs[index].dfd); @@ -6254,7 +6303,7 @@ static void *ss_thread(void *data) ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); callerid_free(cs); ast_hangup(chan); - return NULL; + goto quit; } break; } @@ -6297,12 +6346,12 @@ static void *ss_thread(void *data) ast_log(LOG_WARNING, "CID timed out waiting for ring. " "Exiting simple switch\n"); ast_hangup(chan); - return NULL; + goto quit; } if (!(f = ast_read(chan))) { ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); ast_hangup(chan); - return NULL; + goto quit; } ast_frfree(f); if (chan->_state == AST_STATE_RING || @@ -6333,7 +6382,7 @@ static void *ss_thread(void *data) ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); callerid_free(cs); ast_hangup(chan); - return NULL; + goto quit; } if (i & DAHDI_IOMUX_SIGEVENT) { res = dahdi_get_event(p->subs[index].dfd); @@ -6356,7 +6405,7 @@ static void *ss_thread(void *data) ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); callerid_free(cs); ast_hangup(chan); - return NULL; + goto quit; } break; } @@ -6406,7 +6455,7 @@ static void *ss_thread(void *data) "restarted by the actual ring.\n", chan->name); ast_hangup(chan); - return NULL; + goto quit; } } else if (p->use_callerid && p->cid_start == CID_START_RING) { /* FSK Bell202 callerID */ @@ -6438,7 +6487,7 @@ static void *ss_thread(void *data) ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); callerid_free(cs); ast_hangup(chan); - return NULL; + goto quit; } if (i & DAHDI_IOMUX_SIGEVENT) { res = dahdi_get_event(p->subs[index].dfd); @@ -6449,7 +6498,7 @@ static void *ss_thread(void *data) p->polarity = POLARITY_IDLE; callerid_free(cs); ast_hangup(chan); - return NULL; + goto quit; } res = 0; /* Let us detect callerid when the telco uses distinctive ring */ @@ -6469,7 +6518,7 @@ static void *ss_thread(void *data) ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); callerid_free(cs); ast_hangup(chan); - return NULL; + goto quit; } break; } @@ -6509,7 +6558,7 @@ static void *ss_thread(void *data) ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); callerid_free(cs); ast_hangup(chan); - return NULL; + goto quit; } if (i & DAHDI_IOMUX_SIGEVENT) { res = dahdi_get_event(p->subs[index].dfd); @@ -6532,7 +6581,7 @@ static void *ss_thread(void *data) ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); callerid_free(cs); ast_hangup(chan); - return NULL; + goto quit; } break; } @@ -6608,7 +6657,7 @@ static void *ss_thread(void *data) ast_hangup(chan); ast_log(LOG_WARNING, "PBX exited non-zero\n"); } - return NULL; + goto quit; default: ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); @@ -6619,6 +6668,11 @@ static void *ss_thread(void *data) if (res < 0) ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); ast_hangup(chan); +quit: + ast_mutex_lock(&ss_thread_lock); + ss_thread_count--; + ast_cond_signal(&ss_thread_complete); + ast_mutex_unlock(&ss_thread_lock); return NULL; } @@ -6631,6 +6685,8 @@ static int dahdi_destroy_channel_bynum(int channel) 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); return RESULT_SUCCESS; } @@ -6868,6 +6924,8 @@ static void *do_monitor(void *data) } ast_log(LOG_DEBUG, "Monitor starting...\n"); #endif + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + for (;;) { /* Lock the interface list */ ast_mutex_lock(&iflock); @@ -6906,10 +6964,13 @@ static void *do_monitor(void *data) /* Okay, now that we know what to do, release the interface lock */ ast_mutex_unlock(&iflock); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); /* Wait at least a second for something to happen */ res = poll(pfds, count, 1000); pthread_testcancel(); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + /* Okay, poll has finished. Let's see what happened. */ if (res < 0) { if ((errno != EAGAIN) && (errno != EINTR)) @@ -7237,9 +7298,10 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, tmp2 = tmp2->next; } - if (!here && !reloading) { + if (!here && reloading != 1) { if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { - destroy_dahdi_pvt(&tmp); + if (tmp) + free(tmp); return NULL; } ast_mutex_init(&tmp->lock); @@ -7255,8 +7317,11 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, if ((channel != CHAN_PSEUDO) && !pri) { snprintf(fn, sizeof(fn), "%d", channel); /* Open non-blocking */ - if (!here) + tmp->subs[SUB_REAL].dfd = dahdi_open(fn); + while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */ + usleep(1); tmp->subs[SUB_REAL].dfd = dahdi_open(fn); + } /* Allocate a DAHDI structure */ if (tmp->subs[SUB_REAL].dfd < 0) { ast_log(LOG_ERROR, "Unable to open channel %d: %s\nhere = %d, tmp->channel = %d, channel = %d\n", channel, strerror(errno), here, tmp->channel, channel); @@ -8451,6 +8516,8 @@ static void *pri_dchannel(void *vpri) char plancallingani[256]; char calledtonstr[10]; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + gettimeofday(&lastidle, NULL); if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) { /* Need to do idle dialing, check to be sure though */ @@ -8576,8 +8643,12 @@ static void *pri_dchannel(void *vpri) } ast_mutex_unlock(&pri->lock); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_testcancel(); e = NULL; res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000); + pthread_testcancel(); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); ast_mutex_lock(&pri->lock); if (!res) { @@ -9947,23 +10018,122 @@ static int dahdi_destroy_channel(int fd, int argc, char **argv) return dahdi_destroy_channel_bynum(channel); } +static void dahdi_softhangup_all(void) +{ + struct dahdi_pvt *p; +retry: + ast_mutex_lock(&iflock); + for (p = iflist; p; p = p->next) { + ast_mutex_lock(&p->lock); + if (p->owner && !p->restartpending) { + if (ast_channel_trylock(p->owner)) { + if (option_debug > 2) + ast_verbose("Avoiding deadlock\n"); + /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ + ast_mutex_unlock(&p->lock); + ast_mutex_unlock(&iflock); + goto retry; + } + if (option_debug > 2) + ast_verbose("Softhanging up on %s\n", p->owner->name); + ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); + p->restartpending = 1; + num_restart_pending++; + ast_channel_unlock(p->owner); + } + ast_mutex_unlock(&p->lock); + } + ast_mutex_unlock(&iflock); +} + static int setup_dahdi(int reload); static int dahdi_restart(void) { - if (option_verbose > 0) - ast_verbose(VERBOSE_PREFIX_1 "Destroying channels and reloading %s configuration.\n", dahdi_chan_name); - while (iflist) { - if (option_debug) - ast_log(LOG_DEBUG, "Destroying %s channel no. %d\n", dahdi_chan_name, iflist->channel); - /* Also updates iflist: */ - destroy_channel(NULL, iflist, 1); + int i, j, cancel_code; + struct dahdi_pvt *p; + + ast_mutex_lock(&restart_lock); + + if (option_verbose) + ast_verbose("Destroying channels and reloading DAHDI configuration.\n"); + dahdi_softhangup_all(); + if (option_verbose > 3) + ast_verbose("Initial softhangup of all DAHDI channels complete.\n"); + + #if defined(HAVE_PRI) + for (i = 0; i < NUM_SPANS; i++) { + if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) { + cancel_code = pthread_cancel(pris[i].master); + pthread_kill(pris[i].master, SIGURG); + if (option_debug > 3) + ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code); + pthread_join(pris[i].master, NULL); + if (option_debug > 3) + ast_verbose("Joined thread of span %d\n", i); + } + } + #endif + + ast_mutex_lock(&monlock); + if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { + cancel_code = pthread_cancel(monitor_thread); + pthread_kill(monitor_thread, SIGURG); + if (option_debug > 3) + ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); + pthread_join(monitor_thread, NULL); + if (option_debug > 3) + ast_verbose("Joined monitor thread\n"); + } + monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ + + ast_mutex_lock(&ss_thread_lock); + while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ + int x = DAHDI_FLASH; + if (option_debug > 2) + ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count); + + for (p = iflist; p; p = p->next) { + if (p->owner) + ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */ + } + ast_cond_wait(&ss_thread_complete, &ss_thread_lock); } + + /* ensure any created channels before monitor threads were stopped are hungup */ + dahdi_softhangup_all(); + if (option_verbose > 3) + ast_verbose("Final softhangup of all DAHDI channels complete.\n"); + destroy_all_channels(); if (option_debug) - ast_log(LOG_DEBUG, "Channels destroyed. Now re-reading config.\n"); - if (setup_dahdi(0) != 0) { - ast_log(LOG_WARNING, "Reload channels from %s config failed!\n", dahdi_chan_name); + ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); + + ast_mutex_unlock(&monlock); + + #ifdef HAVE_PRI + for (i = 0; i < NUM_SPANS; i++) { + for (j = 0; j < NUM_DCHANS; j++) + dahdi_close(pris[i].fds[j]); + } + + memset(pris, 0, sizeof(pris)); + for (i = 0; i < NUM_SPANS; i++) { + ast_mutex_init(&pris[i].lock); + pris[i].offset = -1; + pris[i].master = AST_PTHREADT_NULL; + for (j = 0; j < NUM_DCHANS; j++) + pris[i].fds[j] = -1; + } + pri_set_error(dahdi_pri_error); + pri_set_message(dahdi_pri_message); + #endif + + if (setup_dahdi(2) != 0) { + ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); + ast_mutex_unlock(&ss_thread_lock); return 1; } + ast_mutex_unlock(&ss_thread_lock); + ast_mutex_unlock(&restart_lock); return 0; } @@ -10612,7 +10782,7 @@ static int __unload_module(void) struct dahdi_pvt *p, *pl; #ifdef HAVE_PRI - int i; + int i, j; for (i = 0; i < NUM_SPANS; i++) { if (pris[i].master != AST_PTHREADT_NULL) pthread_cancel(pris[i].master); @@ -10676,7 +10846,9 @@ static int __unload_module(void) for (i = 0; i < NUM_SPANS; i++) { if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) pthread_join(pris[i].master, NULL); - dahdi_close(pris[i].fds[i]); + for (j = 0; j < NUM_DCHANS; j++) { + dahdi_close(pris[i].fds[j]); + } } #endif return 0; @@ -11016,7 +11188,7 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct confp->chan.hanguponpolarityswitch = ast_true(v->value); } else if (!strcasecmp(v->name, "sendcalleridafter")) { confp->chan.sendcalleridafter = atoi(v->value); - } else if (!reload){ + } else if (reload != 1){ if (!strcasecmp(v->name, "signalling")) { confp->chan.outsigmod = -1; if (!strcasecmp(v->value, "em")) { @@ -11510,7 +11682,7 @@ static int setup_dahdi(int reload) /* It's a little silly to lock it, but we mind as well just to be sure */ ast_mutex_lock(&iflock); #ifdef HAVE_PRI - if (!reload) { + if (reload != 1) { /* Process trunkgroups first */ v = ast_variable_browse(cfg, "trunkgroups"); while (v) { @@ -11598,7 +11770,7 @@ static int setup_dahdi(int reload) ast_config_destroy(cfg); } #ifdef HAVE_PRI - if (!reload) { + if (reload != 1) { for (x = 0; x < NUM_SPANS; x++) { if (pris[x].pvts[0]) { if (start_pri(pris + x)) {