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",