Index: loader.c
===================================================================
RCS file: /usr/cvsroot/asterisk/loader.c,v
retrieving revision 1.18
diff -u -r1.18 loader.c
--- loader.c	19 Nov 2003 21:19:18 -0000	1.18
+++ loader.c	3 Dec 2003 05:03:10 -0000
@@ -103,6 +103,8 @@
 
 static struct module *module_list=NULL;
 
+static int atexit_registered = 0;
+
 int ast_unload_resource(char *resource_name, int force)
 {
 	struct module *m, *ml = NULL;
@@ -145,6 +147,65 @@
 	return res;
 }
 
+static void ast_unload_modules(void)
+{
+	struct module *m, *ml = NULL;
+	int res = -1;
+	int force = 0;
+	char tmp[80];
+	if (ast_mutex_lock(&modlock))
+		ast_log(LOG_WARNING, "Failed to lock\n");
+	m = module_list;
+	while(m) {
+		if ((res = m->usecount()) > 0)  {
+			if (force) 
+				ast_log(LOG_WARNING, "Warning:  Forcing removal of module %s with use count %d\n", m->resource, res);
+			else {
+//				ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", m->resource, res);
+				m = m->next;
+				continue;
+//				ast_mutex_unlock(&modlock);
+//				return -1;
+			}
+		}
+		if(m->unload_module)
+		{
+			if (option_verbose > 2) 
+				ast_verbose(VERBOSE_PREFIX_3 "=> Unloading module '%s' (%s)\n", m->resource, term_color(tmp, m->description(), COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
+			res = m->unload_module();
+		}
+		else
+			res = 1;
+		if (res) {
+			ast_log(LOG_WARNING, "Firm unload failed for %s\n", m->resource);
+			if (force <= AST_FORCE_FIRM) {
+				m = m->next;
+				continue;
+//				ast_mutex_unlock(&modlock);
+//				return -1;
+			} else
+				ast_log(LOG_WARNING, "** Dangerous **: Unloading resource %s anyway, at user request\n", m->resource);
+		}
+		if (ml)
+			ml->next = m->next;
+		else
+			module_list = m->next;
+		dlclose(m->lib);
+		free(m);
+
+		if(ml)
+			m = ml->next;
+		else
+			m = module_list;
+
+//		ml = m;
+//		m = m->next;
+	}
+	ast_mutex_unlock(&modlock);
+	ast_update_use_count();
+//	return res;
+}
+
 void ast_module_reload(void)
 {
 	struct module *m;
@@ -312,6 +373,11 @@
 		ast_log(LOG_WARNING, "%s: load_module failed, returning %d\n", m->resource, res);
 		ast_unload_resource(resource_name, 0);
 		return -1;
+	}
+	if(!atexit_registered)
+	{
+		ast_register_atexit(ast_unload_modules);
+		atexit_registered = 1;
 	}
 	ast_update_use_count();
 	return 0;
Index: apps/app_qcall.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_qcall.c,v
retrieving revision 1.7
diff -u -r1.7 app_qcall.c
--- apps/app_qcall.c	22 Aug 2003 16:36:33 -0000	1.7
+++ apps/app_qcall.c	3 Dec 2003 05:03:10 -0000
@@ -71,6 +71,7 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/file.h>
+#include <sys/signal.h>
 #include "../astconf.h"
 
 static char qdir[255];
@@ -113,6 +114,8 @@
 	if (debug) printf("@@@@ qcall starting at %s",ctime(&t));
 	for(;;)
 	   {
+	   	pthread_testcancel();
+
 		time(&t);
 		dirp = opendir(qdir);
 		if (!dirp)
@@ -357,6 +360,11 @@
 int unload_module(void)
 {
 	STANDARD_HANGUP_LOCALUSERS;
+	if (qcall_thread) {
+		pthread_cancel(qcall_thread);
+		pthread_kill(qcall_thread, SIGURG);
+		pthread_join(qcall_thread, NULL);
+	}
 	return 0;
 }
 
Index: channels/chan_h323.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_h323.c,v
retrieving revision 1.9
diff -u -r1.9 chan_h323.c
--- channels/chan_h323.c	21 Oct 2003 13:12:30 -0000	1.9
+++ channels/chan_h323.c	3 Dec 2003 05:03:11 -0000
@@ -1775,6 +1775,19 @@
 		ast_log(LOG_WARNING, "Unable to lock the interface list\n");
 		return -1;
 	}
+
+	if (!ast_mutex_lock(&monlock)) {
+		if (monitor_thread) {
+			pthread_cancel(monitor_thread);
+			pthread_kill(monitor_thread, SIGURG);
+			pthread_join(monitor_thread, NULL);
+		}
+		monitor_thread = (pthread_t) -2;
+		ast_mutex_unlock(&monlock);
+	} else {
+		ast_log(LOG_WARNING, "Unable to lock the monitor\n");
+		return -1;
+	}
 		
 	if (!ast_mutex_lock(&iflock)) {
 		/* destroy all the interfaces and free their memory */
@@ -1804,6 +1817,13 @@
 	ast_cli_unregister(&cli_no_trace);
 	ast_cli_unregister(&cli_show_codecs);
 	ast_cli_unregister(&cli_gk_cycle);
+	
+	ast_rtp_proto_unregister(&oh323_rtp);
+	
+	if (sched)
+		sched_context_destroy(sched);
+	if (io)
+		io_context_destroy(io);
 
 	/* unregister channel type */
 	ast_channel_unregister(type);
Index: channels/chan_iax.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_iax.c,v
retrieving revision 1.42
diff -u -r1.42 chan_iax.c
--- channels/chan_iax.c	17 Nov 2003 23:46:54 -0000	1.42
+++ channels/chan_iax.c	3 Dec 2003 05:03:13 -0000
@@ -4515,6 +4515,7 @@
 				ast_iax_frame_free(freeme);
 		}
 		ast_mutex_unlock(&iaxq.lock);
+		pthread_testcancel();
 		res = ast_sched_wait(sched);
 		if ((res > 1000) || (res < 0))
 			res = 1000;
@@ -5431,6 +5432,7 @@
 	int x;
 	/* Cancel the network thread, close the net socket */
 	pthread_cancel(netthreadid);
+	pthread_kill(netthreadid, SIGURG);
 	pthread_join(netthreadid, NULL);
 	close(netsocket);
 	for (x=0;x<AST_IAX_MAX_CALLS;x++)
@@ -5443,8 +5445,15 @@
 	ast_cli_unregister(&cli_set_jitter);
 	ast_cli_unregister(&cli_show_stats);
 	ast_cli_unregister(&cli_show_cache);
+	ast_cli_unregister(&cli_show_registry);
+	ast_cli_unregister(&cli_debug);
+	ast_cli_unregister(&cli_no_debug);
 	ast_unregister_switch(&iax_switch);
 	delete_users();
+	if (io)
+		io_context_destroy(io);
+	if (sched)
+		sched_context_destroy(sched);
 	return 0;
 }
 
Index: channels/chan_iax2.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_iax2.c,v
retrieving revision 1.75
diff -u -r1.75 chan_iax2.c
--- channels/chan_iax2.c	17 Nov 2003 23:46:54 -0000	1.75
+++ channels/chan_iax2.c	3 Dec 2003 05:03:16 -0000
@@ -5021,6 +5021,7 @@
 				iax_frame_free(freeme);
 		}
 		ast_mutex_unlock(&iaxq.lock);
+		pthread_testcancel();
 		res = ast_sched_wait(sched);
 		if ((res > 1000) || (res < 0))
 			res = 1000;
@@ -6030,6 +6031,7 @@
 	int x;
 	/* Cancel the network thread, close the net socket */
 	pthread_cancel(netthreadid);
+	pthread_kill(netthreadid, SIGURG);
 	pthread_join(netthreadid, NULL);
 	close(netsocket);
 	for (x=0;x<IAX_MAX_CALLS;x++)
@@ -6042,8 +6044,16 @@
 	ast_cli_unregister(&cli_set_jitter);
 	ast_cli_unregister(&cli_show_stats);
 	ast_cli_unregister(&cli_show_cache);
+	ast_cli_unregister(&cli_show_registry);
+	ast_cli_unregister(&cli_debug);
+	ast_cli_unregister(&cli_trunk_debug);
+	ast_cli_unregister(&cli_no_debug);
 	ast_unregister_switch(&iax2_switch);
 	delete_users();
+	if (io)
+		io_context_destroy(io);
+	if (sched)
+		sched_context_destroy(sched);
 	return 0;
 }
 
Index: channels/chan_mgcp.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_mgcp.c,v
retrieving revision 1.29
diff -u -r1.29 chan_mgcp.c
--- channels/chan_mgcp.c	8 Sep 2003 16:48:06 -0000	1.29
+++ channels/chan_mgcp.c	3 Dec 2003 05:03:17 -0000
@@ -3067,6 +3067,10 @@
 		ast_log(LOG_WARNING, "Unable to lock the monitor\n");
 		return -1;
 	}
+	if (io)
+		io_context_destroy(io);
+	if (sched)
+		sched_context_destroy(sched);
 #endif		
 	return -1;
 }
Index: channels/chan_phone.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_phone.c,v
retrieving revision 1.21
diff -u -r1.21 chan_phone.c
--- channels/chan_phone.c	17 Sep 2003 04:39:22 -0000	1.21
+++ channels/chan_phone.c	3 Dec 2003 05:03:17 -0000
@@ -30,6 +30,7 @@
 #include <arpa/inet.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
+#include <sys/signal.h>
 #include <linux/telephony.h>
 /* Still use some IXJ specific stuff */
 #include <linux/ixjuser.h>
@@ -848,6 +849,8 @@
 		/* Okay, now that we know what to do, release the interface lock */
 		ast_mutex_unlock(&iflock);
 		
+		pthread_testcancel();
+		
 		/* And from now on, we're okay to be killed, so release the monitor lock as well */
 		ast_mutex_unlock(&monlock);
 		/* Wait indefinitely for something to happen */
@@ -923,9 +926,8 @@
 	}
 	if (monitor_thread != -1) {
 		pthread_cancel(monitor_thread);
-#if 0
+		pthread_kill(monitor_thread, SIGURG);
 		pthread_join(monitor_thread, NULL);
-#endif
 	}
 	/* Start a new monitor */
 	if (pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
@@ -1169,6 +1171,7 @@
 	if (!ast_mutex_lock(&monlock)) {
 		if (monitor_thread > -1) {
 			pthread_cancel(monitor_thread);
+			pthread_kill(monitor_thread, SIGURG);
 			pthread_join(monitor_thread, NULL);
 		}
 		monitor_thread = -2;
Index: channels/chan_sip.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v
retrieving revision 1.259
diff -u -r1.259 chan_sip.c
--- channels/chan_sip.c	28 Nov 2003 04:01:25 -0000	1.259
+++ channels/chan_sip.c	3 Dec 2003 05:03:20 -0000
@@ -5512,6 +5512,7 @@
 		ast_mutex_unlock(&iflock);
 		/* Don't let anybody kill us right away.  Nobody should lock the interface list
 		   and wait for the monitor list, but the other way around is okay. */
+#if 0
 		ast_mutex_lock(&monlock);
 		/* Lock the network interface */
 		ast_mutex_lock(&netlock);
@@ -5520,6 +5521,7 @@
 		/* And from now on, we're okay to be killed, so release the monitor lock as well */
 		ast_mutex_unlock(&monlock);
 		pthread_testcancel();
+#endif
 		/* Wait for sched or io */
 		res = ast_sched_wait(sched);
 		if ((res < 0) || (res > 1000))
@@ -5528,6 +5530,7 @@
 		if (fastrestart)
 			res = 1;
 		res = ast_io_wait(io, res);
+		pthread_testcancel();
 		ast_mutex_lock(&monlock);
 		if (res >= 0) 
 			ast_sched_runq(sched);
@@ -6500,6 +6503,15 @@
 	/* First, take us out of the channel loop */
 	ast_channel_unregister(type);
 	ast_unregister_application(app_dtmfmode);
+	ast_cli_unregister(&cli_show_users);
+	ast_cli_unregister(&cli_show_channels);
+	ast_cli_unregister(&cli_show_channel);
+	ast_cli_unregister(&cli_show_peers);
+	ast_cli_unregister(&cli_show_registry);
+	ast_cli_unregister(&cli_debug);
+	ast_cli_unregister(&cli_no_debug);
+	ast_cli_unregister(&cli_inuse_show);
+	ast_rtp_proto_unregister(&sip_rtp);
 	if (!ast_mutex_lock(&iflock)) {
 		/* Hangup all interfaces if they have an owner */
 		p = iflist;
@@ -6542,6 +6554,11 @@
 		ast_log(LOG_WARNING, "Unable to lock the monitor\n");
 		return -1;
 	}
+	
+	if (io)
+		io_context_destroy(io);
+	if (sched)
+		sched_context_destroy(sched);
 		
 	return 0;
 }
Index: channels/chan_skinny.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_skinny.c,v
retrieving revision 1.22
diff -u -r1.22 chan_skinny.c
--- channels/chan_skinny.c	22 Nov 2003 19:15:34 -0000	1.22
+++ channels/chan_skinny.c	3 Dec 2003 05:03:22 -0000
@@ -2701,11 +2701,16 @@
 #if 0	
 	struct skinny_subchannel *p, *pl;
 
-	ast_channel_unregister(type);
         ast_verbose("Skinny module unloading\n");
         
 	/* First, take us out of the channel loop */
 	ast_channel_unregister(type);
+
+	ast_rtp_proto_register(&skinny_rtp);
+
+	ast_cli_unregister(&cli_show_lines);
+	ast_cli_unregister(&cli_debug);
+	ast_cli_unregister(&cli_no_debug);
 	
 	/* close all IP connections */
 	if (!ast_mutex_lock(&devicelock)) {
@@ -2750,6 +2755,10 @@
 		ast_log(LOG_WARNING, "Unable to lock the monitor\n");
 		return -1;
 	}
+	if (io)
+		io_context_destroy(io);
+	if (sched)
+		sched_context_destroy(sched);
 #endif
 	/* if we're still here something was fscked up */   
 	return -1;
Index: channels/chan_zap.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_zap.c,v
retrieving revision 1.147
diff -u -r1.147 chan_zap.c
--- channels/chan_zap.c	2 Dec 2003 23:09:04 -0000	1.147
+++ channels/chan_zap.c	3 Dec 2003 05:03:25 -0000
@@ -7323,6 +7323,15 @@
 	/* First, take us out of the channel loop */
 	ast_channel_unregister(type);
 	ast_channel_unregister(typecompat);
+#ifdef ZAPATA_PRI
+	ast_cli_unregister(&pri_debug);
+	ast_cli_unregister(&pri_no_debug);
+	ast_cli_unregister(&pri_really_debug);
+#endif	
+#ifdef ZAPATA_R2
+	ast_cli_unregister(&r2_debug);
+	ast_cli_unregister(&r2_no_debug);
+#endif	
 	ast_cli_unregister(&cli_show_channels);
 	ast_cli_unregister(&cli_show_channel);
 	ast_cli_unregister(&cli_destroy_channel);
Index: channels/chan_zap_old.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_zap_old.c,v
retrieving revision 1.6
diff -u -r1.6 chan_zap_old.c
--- channels/chan_zap_old.c	29 Sep 2003 20:13:54 -0000	1.6
+++ channels/chan_zap_old.c	3 Dec 2003 05:03:28 -0000
@@ -6820,6 +6820,15 @@
 	/* First, take us out of the channel loop */
 	ast_channel_unregister(type);
 	ast_channel_unregister(typecompat);
+#ifdef ZAPATA_PRI
+	ast_cli_unregister(&pri_debug);
+	ast_cli_unregister(&pri_no_debug);
+	ast_cli_unregister(&pri_really_debug);
+#endif	
+#ifdef ZAPATA_R2
+	ast_cli_unregister(&r2_debug);
+	ast_cli_unregister(&r2_no_debug);
+#endif	
 	ast_cli_unregister(&cli_show_channels);
 	ast_cli_unregister(&cli_show_channel);
 	ast_cli_unregister(&cli_destroy_channel);
