diff --git a/main/autoservice.c b/main/autoservice.c
index fcc42911f7366c1239ee46bf166c73453fd6a3ba..7fb86dad7be294521900de6016571a3511581dd7 100644
--- a/main/autoservice.c
+++ b/main/autoservice.c
@@ -60,6 +60,8 @@ static AST_RWLIST_HEAD_STATIC(aslist, asent);
 
 static pthread_t asthread = AST_PTHREADT_NULL;
 
+static int as_chan_list_state;
+
 static void defer_frame(struct ast_channel *chan, struct ast_frame *f)
 {
 	struct ast_frame *dup_f;
@@ -83,6 +85,11 @@ static void *autoservice_run(void *ign)
 		int x = 0, ms = 500;
 
 		AST_RWLIST_RDLOCK(&aslist);
+
+		/* At this point, we know that no channels that have been removed are going
+		 * to get used again. */
+		as_chan_list_state++;
+
 		AST_RWLIST_TRAVERSE(&aslist, as, list) {
 			if (!ast_check_hangup(as->chan)) {
 				if (x < MAX_AUTOMONS)
@@ -207,10 +214,18 @@ int ast_autoservice_stop(struct ast_channel *chan)
 	struct ast_frame *f;
 	int removed = 0;
 	int orig_end_dtmf_flag = 0;
+	int chan_list_state;
 
 	AST_LIST_HEAD_INIT_NOLOCK(&dtmf_frames);
 
 	AST_RWLIST_WRLOCK(&aslist);
+
+	/* Save the autoservice channel list state.  We _must_ verify that the channel
+	 * list has been rebuilt before we return.  Because, after we return, the channel
+	 * could get destroyed and we don't want our poor autoservice thread to step on
+	 * it after its gone! */
+	chan_list_state = as_chan_list_state;
+
 	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&aslist, as, list) {	
 		if (as->chan == chan) {
 			AST_RWLIST_REMOVE_CURRENT(list);
@@ -248,5 +263,8 @@ int ast_autoservice_stop(struct ast_channel *chan)
 		ast_frfree(f);
 	}
 
+	while (chan_list_state == as_chan_list_state)
+		usleep(1000);
+
 	return res;
 }