diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c
index 9a66b75188bef89e90fc4b092e9cd02ccc7f5efc..2badd520cce7b5b3c3b8e6790cdfdabed61234f4 100644
--- a/res/res_musiconhold.c
+++ b/res/res_musiconhold.c
@@ -149,6 +149,9 @@ struct mohclass {
 	int srcfd;
 	/*! FD for timing source */
 	int pseudofd;
+	/*! Number of users */
+	int inuse;
+	unsigned int delete:1;
 	AST_LIST_HEAD_NOLOCK(, mohdata) members;
 	AST_LIST_ENTRY(mohclass) list;
 };
@@ -167,6 +170,8 @@ AST_RWLIST_HEAD_STATIC(mohclasses, mohclass);
 #define MPG_123 "/usr/bin/mpg123"
 #define MAX_MP3S 256
 
+static int ast_moh_destroy_one(struct mohclass *moh);
+static int reload(void);
 
 static void ast_moh_free_class(struct mohclass **mohclass) 
 {
@@ -209,6 +214,8 @@ static void moh_files_release(struct ast_channel *chan, void *data)
 		}
 		state->save_pos = state->pos;
 	}
+	if (state->class->delete && ast_atomic_dec_and_test(&state->class->inuse))
+		ast_moh_destroy_one(state->class);
 }
 
 
@@ -713,6 +720,8 @@ static void moh_release(struct ast_channel *chan, void *data)
 	close(moh->pipe[0]);
 	close(moh->pipe[1]);
 	oldwfmt = moh->origwfmt;
+	if (moh->parent->delete && ast_atomic_dec_and_test(&moh->parent->inuse))
+		ast_moh_destroy_one(moh->parent);
 	ast_free(moh);
 	if (chan) {
 		if (oldwfmt && ast_set_write_format(chan, oldwfmt)) 
@@ -871,8 +880,11 @@ static int moh_register(struct mohclass *moh, int reload)
 #ifdef HAVE_ZAPTEL
 	int x;
 #endif
+	struct mohclass *mohclass = NULL;
+
 	AST_RWLIST_WRLOCK(&mohclasses);
-	if (get_mohbyname(moh->name, 0)) {
+	if ((mohclass = get_mohbyname(moh->name, 0))) {
+		mohclass->delete = 0;
 		if (reload) {
 			ast_debug(1, "Music on Hold class '%s' left alone from initial load.\n", moh->name);
 		} else {
@@ -971,6 +983,8 @@ static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, con
 		mohclass = get_mohbyname(interpclass, 1);
 	if (!mohclass)	
 		mohclass = get_mohbyname("default", 1);
+	if (mohclass)
+		ast_atomic_fetchadd_int(&mohclass->inuse, +1);
 	AST_RWLIST_UNLOCK(&mohclasses);
 
 	if (!mohclass)
@@ -1000,7 +1014,7 @@ static struct mohclass *moh_class_malloc(void)
 {
 	struct mohclass *class;
 
-	if ((class = ast_calloc(1, sizeof(*class))))		
+	if ((class = ast_calloc(1, sizeof(*class))))
 		class->format = AST_FORMAT_SLINEAR;
 
 	return class;
@@ -1020,6 +1034,14 @@ static int load_moh_classes(int reload)
 	if (cfg == NULL || cfg == CONFIG_STATUS_FILEUNCHANGED)
 		return 0;
 
+	if (reload) {
+		AST_RWLIST_WRLOCK(&mohclasses);
+		AST_RWLIST_TRAVERSE(&mohclasses, class, list) {
+			class->delete = 1;
+		}
+		AST_RWLIST_UNLOCK(&mohclasses);
+	}
+
 	cat = ast_category_browse(cfg, NULL);
 	for (; cat; cat = ast_category_browse(cfg, cat)) {
 		/* These names were deprecated in 1.4 and should not be used until after the next major release. */
@@ -1082,16 +1104,12 @@ static int load_moh_classes(int reload)
 	return numclasses;
 }
 
-static void ast_moh_destroy(void)
+static int ast_moh_destroy_one(struct mohclass *moh)
 {
-	struct mohclass *moh;
 	char buff[8192];
 	int bytes, tbytes = 0, stime = 0, pid = 0;
 
-	ast_verb(2, "Destroying musiconhold processes\n");
-
-	AST_RWLIST_WRLOCK(&mohclasses);
-	while ((moh = AST_RWLIST_REMOVE_HEAD(&mohclasses, list))) {
+	if (moh) {
 		if (moh->pid > 1) {
 			ast_debug(1, "killing %d!\n", moh->pid);
 			stime = time(NULL) + 2;
@@ -1112,33 +1130,27 @@ static void ast_moh_destroy(void)
 		}
 		ast_moh_free_class(&moh);
 	}
-	AST_RWLIST_UNLOCK(&mohclasses);
+
+	return 0;
 }
 
-static void moh_on_off(int on)
+static void ast_moh_destroy(void)
 {
-	struct ast_channel *chan = NULL;
-
-	while ( (chan = ast_channel_walk_locked(chan)) != NULL) {
-		if (ast_test_flag(chan, AST_FLAG_MOH)) {
-			if (on)
-				local_ast_moh_start(chan, NULL, NULL);
-			else
-				ast_deactivate_generator(chan);
-		}
-		ast_channel_unlock(chan);
+	struct mohclass *moh;
+
+	ast_verb(2, "Destroying musiconhold processes\n");
+
+	AST_RWLIST_WRLOCK(&mohclasses);
+	while ((moh = AST_RWLIST_REMOVE_HEAD(&mohclasses, list))) {
+		ast_moh_destroy_one(moh);
 	}
+	AST_RWLIST_UNLOCK(&mohclasses);
 }
 
 static int moh_cli(int fd, int argc, char *argv[]) 
 {
-	int x;
+	reload();
 
-	moh_on_off(0);
-	ast_moh_destroy();
-	x = load_moh_classes(1);
-	moh_on_off(1);
-	ast_cli(fd, "\n%d class%s reloaded.\n", x, x == 1 ? "" : "es");
 	return 0;
 }
 
@@ -1170,6 +1182,7 @@ static int moh_classes_show(int fd, int argc, char *argv[])
 		ast_cli(fd, "Class: %s\n", class->name);
 		ast_cli(fd, "\tMode: %s\n", S_OR(class->mode, "<none>"));
 		ast_cli(fd, "\tDirectory: %s\n", S_OR(class->dir, "<none>"));
+		ast_cli(fd, "\tUse Count: %d\n", class->inuse);
 		if (class->digit)
 			ast_cli(fd, "\tDigit: %c\n", class->digit);
 		if (ast_test_flag(class, MOH_CUSTOM))
@@ -1204,10 +1217,15 @@ static int init_classes(int reload)
 		return 0;			/* Return if nothing is found */
 
 	AST_RWLIST_WRLOCK(&mohclasses);
-	AST_RWLIST_TRAVERSE(&mohclasses, moh, list) {
-		if (moh->total_files)
+	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mohclasses, moh, list) {
+		if (reload && moh->delete) {
+			AST_RWLIST_REMOVE_CURRENT(&mohclasses, list);
+			if (!moh->inuse)
+				ast_moh_destroy_one(moh);
+		} else if (moh->total_files)
 			moh_scan_files(moh);
 	}
+	AST_RWLIST_TRAVERSE_SAFE_END
 	AST_RWLIST_UNLOCK(&mohclasses);
 
 	return 1;