diff --git a/res/res_calendar.c b/res/res_calendar.c index 01f5f95c118ef1f8834fa11782b703d0ca396494..14846d3167c492e97091e38578bcc7a5c411ef9c 100644 --- a/res/res_calendar.c +++ b/res/res_calendar.c @@ -216,6 +216,7 @@ static pthread_t refresh_thread = AST_PTHREADT_NULL; static ast_mutex_t refreshlock; static ast_cond_t refresh_condition; static ast_mutex_t reloadlock; +static int module_unloading; static void event_notification_destroy(void *data); static void *event_notification_duplicate(void *data); @@ -1013,9 +1014,9 @@ void ast_calendar_merge_events(struct ast_calendar *cal, struct ao2_container *n } -static int load_config(void *data) +static int load_config(int reload) { - struct ast_flags config_flags = { CONFIG_FLAG_FILEUNCHANGED }; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; struct ast_config *tmpcfg; if (!(tmpcfg = ast_config_load2("calendar.conf", "calendar", config_flags)) || @@ -1734,7 +1735,7 @@ static int reload(void) /* Mark existing calendars for deletion */ ao2_callback(calendars, OBJ_NODATA | OBJ_MULTIPLE, cb_pending_deletion, NULL); - load_config(NULL); + load_config(1); AST_LIST_LOCK(&techs); AST_LIST_TRAVERSE(&techs, iter, list) { @@ -1761,15 +1762,21 @@ static void *do_refresh(void *data) ast_mutex_lock(&refreshlock); - if ((wait = ast_sched_wait(sched)) < 0) { - wait = 1000; - } - - ts.tv_sec = (now.tv_sec + wait / 1000) + 1; - ast_cond_timedwait(&refresh_condition, &refreshlock, &ts); + while (!module_unloading) { + if ((wait = ast_sched_wait(sched)) < 0) { + wait = 1000; + } + ts.tv_sec = (now.tv_sec + wait / 1000) + 1; + if (ast_cond_timedwait(&refresh_condition, &refreshlock, &ts) == ETIMEDOUT) { + break; + } + } ast_mutex_unlock(&refreshlock); + if (module_unloading) { + break; + } ast_sched_runq(sched); } @@ -1792,12 +1799,22 @@ static int unload_module(void) /* Remove all calendars */ ao2_callback(calendars, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL); + ast_mutex_lock(&refreshlock); + module_unloading = 1; + ast_cond_signal(&refresh_condition); + ast_mutex_unlock(&refreshlock); + pthread_join(refresh_thread, NULL); + AST_LIST_LOCK(&techs); - AST_LIST_TRAVERSE(&techs, tech, list) { + AST_LIST_TRAVERSE_SAFE_BEGIN(&techs, tech, list) { ast_unload_resource(tech->module, 0); } + AST_LIST_TRAVERSE_SAFE_END; AST_LIST_UNLOCK(&techs); + ast_config_destroy(calendar_config); + calendar_config = NULL; + return 0; } @@ -1808,7 +1825,7 @@ static int load_module(void) return AST_MODULE_LOAD_FAILURE; } - if (load_config(NULL)) { + if (load_config(0)) { /* We don't have calendar support enabled */ return AST_MODULE_LOAD_DECLINE; } @@ -1835,9 +1852,6 @@ static int load_module(void) ast_devstate_prov_add("Calendar", calendarstate); - /* Since other modules depend on this, disable unloading */ - ast_module_ref(ast_module_info->self); - return AST_MODULE_LOAD_SUCCESS; } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Asterisk Calendar integration",