diff --git a/asterisk.c b/asterisk.c index 05b84308f700222be1979988731396f9ae8fbcea..ccc38457477aac18234e13195b86d9835e246e76 100755 --- a/asterisk.c +++ b/asterisk.c @@ -71,6 +71,12 @@ struct console { pthread_t t; /* Thread of handler */ }; +static struct ast_atexit { + void (*func)(void); + struct ast_atexit *next; +} *atexits = NULL; +static pthread_mutex_t atexitslock = AST_MUTEX_INITIALIZER; + time_t ast_startuptime; time_t ast_lastreloadtime; @@ -99,6 +105,43 @@ char ast_config_AST_PID[AST_CONFIG_MAX_PATH]; char ast_config_AST_SOCKET[AST_CONFIG_MAX_PATH]; char ast_config_AST_RUN_DIR[AST_CONFIG_MAX_PATH]; +int ast_register_atexit(void (*func)(void)) +{ + int res = -1; + struct ast_atexit *ae; + ast_unregister_atexit(func); + ae = malloc(sizeof(struct ast_atexit)); + ast_pthread_mutex_lock(&atexitslock); + if (ae) { + memset(ae, 0, sizeof(struct ast_atexit)); + ae->next = atexits; + ae->func = func; + atexits = ae; + res = 0; + } + ast_pthread_mutex_unlock(&atexitslock); + return res; +} + +void ast_unregister_atexit(void (*func)(void)) +{ + struct ast_atexit *ae, *prev = NULL; + ast_pthread_mutex_lock(&atexitslock); + ae = atexits; + while(ae) { + if (ae->func == func) { + if (prev) + prev->next = ae->next; + else + atexits = ae->next; + break; + } + prev = ae; + ae = ae->next; + } + ast_pthread_mutex_unlock(&atexitslock); +} + static int fdprint(int fd, const char *s) { return write(fd, s, strlen(s) + 1); @@ -356,6 +399,19 @@ static char *_argv[256]; static int shuttingdown = 0; +static void ast_run_atexits(void) +{ + struct ast_atexit *ae; + ast_pthread_mutex_lock(&atexitslock); + ae = atexits; + while(ae) { + if (ae->func) + ae->func(); + ae = ae->next; + } + ast_pthread_mutex_unlock(&atexitslock); +} + static void quit_handler(int num, int nice, int safeshutdown, int restart) { char filename[80] = ""; @@ -411,6 +467,9 @@ static void quit_handler(int num, int nice, int safeshutdown, int restart) if (el_hist != NULL) history_end(el_hist); } + if (option_verbose) + ast_verbose("Executing last minute cleanups\n"); + ast_run_atexits(); /* Called on exit */ if (option_verbose && option_console) ast_verbose("Asterisk %s ending (%d).\n", ast_active_channels() ? "uncleanly" : "cleanly", num); @@ -437,8 +496,8 @@ static void quit_handler(int num, int nice, int safeshutdown, int restart) if (option_verbose || option_console) ast_verbose("Restarting Asterisk NOW...\n"); execvp(_argv[0], _argv); - } else - exit(0); + } + exit(0); } static void __quit_handler(int num) diff --git a/channels/chan_zap.c b/channels/chan_zap.c index 915d5e912f0a4ce8d070f0bb963558d44f105f82..37c9991959c6220a9d40ff909f713857ef2d03cc 100755 --- a/channels/chan_zap.c +++ b/channels/chan_zap.c @@ -355,6 +355,7 @@ static struct zt_pvt { float rxgain; float txgain; struct zt_pvt *next; /* Next channel in list */ + struct zt_pvt *prev; /* Prev channel in list */ char context[AST_MAX_EXTENSION]; char exten[AST_MAX_EXTENSION]; char language[MAX_LANGUAGE]; @@ -448,7 +449,7 @@ static struct zt_pvt { int r2blocked; int sigchecked; #endif -} *iflist = NULL; +} *iflist = NULL, *ifend = NULL; #ifdef ZAPATA_PRI static inline int pri_grab(struct zt_pvt *pvt, struct zt_pri *pri) @@ -1433,8 +1434,16 @@ static int destroy_channel(struct zt_pvt *prev, struct zt_pvt *cur, int now) if (!owned) { if (prev) { prev->next = cur->next; + if (prev->next) + prev->next->prev = prev; + else + ifend = prev; } else { iflist = cur->next; + if (iflist) + iflist->prev = NULL; + else + ifend = NULL; } if (cur->subs[SUB_REAL].zfd > -1) { zt_close(cur->subs[SUB_REAL].zfd); @@ -1444,8 +1453,16 @@ static int destroy_channel(struct zt_pvt *prev, struct zt_pvt *cur, int now) } else { if (prev) { prev->next = cur->next; + if (prev->next) + prev->next->prev = prev; + else + ifend = prev; } else { iflist = cur->next; + if (iflist) + iflist->prev = NULL; + else + ifend = NULL; } if (cur->subs[SUB_REAL].zfd > -1) { zt_close(cur->subs[SUB_REAL].zfd); @@ -4743,11 +4760,14 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio) for (x=0;x<3;x++) tmp->subs[x].zfd = -1; tmp->next = tmp2; - if (!prev) { + if (!ifend) { iflist = tmp; + tmp->prev = NULL; } else { - prev->next = tmp; + ifend->next = tmp; + tmp->prev = ifend; } + ifend = tmp; } if (tmp) { @@ -5141,6 +5161,7 @@ static struct ast_channel *zt_request(char *type, int format, void *data) char *s; char opt=0; int res=0, y=0; + int backwards = 0; /* We do signed linear */ oldformat = format; @@ -5155,7 +5176,7 @@ static struct ast_channel *zt_request(char *type, int format, void *data) ast_log(LOG_WARNING, "Channel requested with no data\n"); return NULL; } - if (dest[0] == 'g') { + if (toupper(dest[0]) == 'G') { /* Retrieve the group number */ char *stringp=NULL; stringp=dest + 1; @@ -5166,6 +5187,8 @@ static struct ast_channel *zt_request(char *type, int format, void *data) return NULL; } groupmatch = 1 << x; + if (dest[0] == 'G') + backwards = 1; } else { char *stringp=NULL; stringp=dest; @@ -5185,7 +5208,10 @@ static struct ast_channel *zt_request(char *type, int format, void *data) ast_log(LOG_ERROR, "Unable to lock interface list???\n"); return NULL; } - p = iflist; + if (backwards) + p = ifend; + else + p = iflist; while(p && !tmp) { if (available(p, channelmatch, groupmatch)) { if (option_debug) @@ -5232,7 +5258,10 @@ static struct ast_channel *zt_request(char *type, int format, void *data) tmp->cdrflags |= AST_CDR_CALLWAIT; break; } - p = p->next; + if (backwards) + p = p->prev; + else + p = p->next; } ast_pthread_mutex_unlock(&iflock); restart_monitor(); diff --git a/include/asterisk/module.h b/include/asterisk/module.h index 93d059d95ba80dabeae66a665c108c8da8c41441..39eabce8e6b74c7a483593893748728b4c373f3b 100755 --- a/include/asterisk/module.h +++ b/include/asterisk/module.h @@ -140,6 +140,9 @@ int ast_loader_unregister(int (*updater)(void)); */ void ast_module_reload(void); +int ast_register_atexit(void (*func)(void)); +void ast_unregister_atexit(void (*func)(void)); + /* Local user routines keep track of which channels are using a given module resource. They can help make removing modules safer, particularly if they're in use at the time they have been requested to be removed */ diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c index 7dd88572b59c05ef2aa143e343e643a977d0181f..d99d8bd498280f5dbad5c16f1e603f7fc3183040 100755 --- a/res/res_musiconhold.c +++ b/res/res_musiconhold.c @@ -574,6 +574,8 @@ static void load_moh_classes(void) static void ast_moh_destroy(void) { struct mohclass *moh; + if (option_verbose > 1) + ast_verbose(VERBOSE_PREFIX_2 "Destroying any remaining musiconhold processes\n"); ast_pthread_mutex_lock(&moh_lock); moh = mohclasses; while(moh) { @@ -591,7 +593,7 @@ int load_module(void) int res; load_moh_classes(); res = ast_register_application(app0, moh0_exec, synopsis0, descrip0); - atexit(ast_moh_destroy); + ast_register_atexit(ast_moh_destroy); if (!res) res = ast_register_application(app1, moh1_exec, synopsis1, descrip1); if (!res)