diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index af83c8a4de60c02ca328afe62e345b1cf06c7ea4..394a5f1bacb84c6824d9a4c4b1cce9643730a48d 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -228,7 +228,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
    In normal operation, the macros defined will throw away the tags, so they do not
    affect the speed of the program at all. They can be considered to be documentation.
 */
-/* #define  REF_DEBUG 1 */
+#define  REF_DEBUG 1
 #include "asterisk/lock.h"
 #include "asterisk/config.h"
 #include "asterisk/module.h"
@@ -2789,36 +2789,25 @@ cleanup:
 	return NULL;
 }
 
-/* this func is used with ao2_callback to unlink/delete all marked
-   peers */
-static int peer_is_marked(void *peerobj, void *arg, int flags)
-{
-	struct sip_peer *peer = peerobj;
-	if (peer->the_mark && peer->pokeexpire != -1) {
-		AST_SCHED_DEL(sched, peer->pokeexpire);
-	}
-	return peer->the_mark ? CMP_MATCH : 0;
-}
-
-
-/* \brief Unlink all marked peers from ao2 containers */
-static void unlink_marked_peers_from_tables(void)
+#ifdef REF_DEBUG
+#define ref_peer(arg1,arg2) _ref_peer((arg1),(arg2), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define unref_peer(arg1,arg2) _unref_peer((arg1),(arg2), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+static struct sip_peer *_ref_peer(struct sip_peer *peer, char *tag, char *file, int line, const char *func)
 {
-	ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, NULL,
-						"initiating callback to remove marked peers");
-	ao2_t_callback(peers_by_ip, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, NULL,
-						"initiating callback to remove marked peers");
+	if (peer)
+		__ao2_ref_debug(peer, 1, tag, file, line, func);
+	else
+		ast_log(LOG_ERROR, "Attempt to Ref a null peer pointer\n");
+	return peer;
 }
 
-/* \brief Unlink single peer from all ao2 containers */
-static void unlink_peer_from_tables(struct sip_peer *peer)
+static struct sip_peer *_unref_peer(struct sip_peer *peer, char *tag, char *file, int line, const char *func)
 {
-	ao2_t_unlink(peers, peer, "ao2_unlink of peer from peers table");
-	if (!ast_sockaddr_isnull(&peer->addr)) {
-		ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table");
-	}
+	if (peer)
+		__ao2_ref_debug(peer, -1, tag, file, line, func);
+	return NULL;
 }
-
+#else
 /*!
  * helper functions to unreference various types of objects.
  * By handling them this way, we don't have to declare the
@@ -2835,6 +2824,66 @@ static struct sip_peer *ref_peer(struct sip_peer *peer, char *tag)
 	ao2_t_ref(peer, 1, tag);
 	return peer;
 }
+#endif /* REF_DEBUG */
+
+static void peer_sched_cleanup(struct sip_peer *peer)
+{
+	if (peer->pokeexpire != -1) {
+		AST_SCHED_DEL_UNREF(sched, peer->pokeexpire,
+				unref_peer(peer, "removing poke peer ref"));
+	}
+	if (peer->expire != -1) {
+		AST_SCHED_DEL_UNREF(sched, peer->expire,
+				unref_peer(peer, "remove register expire ref"));
+	}
+}
+
+typedef enum {
+	SIP_PEERS_MARKED,
+	SIP_PEERS_ALL,
+} peer_unlink_flag_t;
+
+/* this func is used with ao2_callback to unlink/delete all marked or linked
+   peers, depending on arg */
+static int match_and_cleanup_peer_sched(void *peerobj, void *arg, int flags)
+{
+	struct sip_peer *peer = peerobj;
+	peer_unlink_flag_t which = *(peer_unlink_flag_t *)arg;
+
+	if (which == SIP_PEERS_ALL || peer->the_mark) {
+		peer_sched_cleanup(peer);
+		return CMP_MATCH;
+	}
+	return 0;
+}
+
+static void unlink_peers_from_tables(peer_unlink_flag_t flag)
+{
+	ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE,
+		match_and_cleanup_peer_sched, &flag, "initiating callback to remove marked peers");
+	ao2_t_callback(peers_by_ip, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE,
+		match_and_cleanup_peer_sched, &flag, "initiating callback to remove marked peers");
+}
+
+/* \brief Unlink all marked peers from ao2 containers */
+static void unlink_marked_peers_from_tables(void)
+{
+	unlink_peers_from_tables(SIP_PEERS_MARKED);
+}
+
+static void unlink_all_peers_from_tables(void)
+{
+	unlink_peers_from_tables(SIP_PEERS_ALL);
+}
+
+/* \brief Unlink single peer from all ao2 containers */
+static void unlink_peer_from_tables(struct sip_peer *peer)
+{
+	ao2_t_unlink(peers, peer, "ao2_unlink of peer from peers table");
+	if (!ast_sockaddr_isnull(&peer->addr)) {
+		ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table");
+	}
+}
 
 /*! \brief maintain proper refcounts for a sip_pvt's outboundproxy
  *
@@ -2947,6 +2996,10 @@ void *dialog_unlink_all(struct sip_pvt *dialog, int lockowner, int lockdialoglis
 		AST_SCHED_DEL_UNREF(sched, dialog->t38id, dialog_unref(dialog, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr"));
 	}
 
+	if (dialog->stimer) {
+		stop_session_timer(dialog);
+	}
+
 	dialog_unref(dialog, "Let's unbump the count in the unlink so the poor pvt can disappear if it is time");
 	return NULL;
 }
@@ -3879,22 +3932,15 @@ void sip_scheddestroy(struct sip_pvt *p, int ms)
  */
 int sip_cancel_destroy(struct sip_pvt *p)
 {
-	int res = 0;
-
 	if (p->final_destruction_scheduled) {
-		return res;
+		return 0;
 	}
 
 	if (p->autokillid > -1) {
-		int res3;
-
-		if (!(res3 = ast_sched_del(sched, p->autokillid))) {
-			append_history(p, "CancelDestroy", "");
-			p->autokillid = -1;
-			dialog_unref(p, "dialog unrefd because autokillid is de-sched'd");
-		}
+		append_history(p, "CancelDestroy", "");
+		AST_SCHED_DEL_UNREF(sched, p->autokillid, dialog_unref(p, "remove ref for autokillid"));
 	}
-	return res;
+	return 0;
 }
 
 /*! \brief Acknowledges receipt of a packet and stops retransmission
@@ -5496,7 +5542,10 @@ void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist)
 {
 	struct sip_request *req;
 
-	if (p->stimer) {
+	/* Destroy Session-Timers if allocated */
+ 	if (p->stimer) {
+		p->stimer->quit_flag = 1;
+		stop_session_timer(p);
 		ast_free(p->stimer);
 		p->stimer = NULL;
 	}
@@ -5572,17 +5621,6 @@ void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist)
 	}
 	deinit_req(&p->initreq);
 
-	/* Destroy Session-Timers if allocated */
-	if (p->stimer) {
-		p->stimer->quit_flag = 1;
-		if (p->stimer->st_active == TRUE && p->stimer->st_schedid > -1) {
-			AST_SCHED_DEL_UNREF(sched, p->stimer->st_schedid,
-					dialog_unref(p, "removing session timer ref"));
-		}
-		ast_free(p->stimer);
-		p->stimer = NULL;
-	}
-
 	/* Clear history */
 	if (p->history) {
 		struct sip_history *hist;
@@ -6537,7 +6575,7 @@ static int interpret_t38_parameters(struct sip_pvt *p, const struct ast_control_
 		struct ast_control_t38_parameters parameters = p->t38.their_parms;
 
 		if (p->t38.state == T38_PEER_REINVITE) {
-			AST_SCHED_DEL(sched, p->t38id);
+			AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr"));
 			parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
 			parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
 			ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
@@ -7798,7 +7836,7 @@ static struct ast_channel *sip_pvt_lock_full(struct sip_pvt *pvt)
 /*! \brief find or create a dialog structure for an incoming SIP message.
  * Connect incoming SIP message to current dialog or create new dialog structure
  * Returns a reference to the sip_pvt object, remember to give it back once done.
- *     Called by handle_incoming(), sipsock_read
+ *     Called by handle_request_do
  */
 static struct sip_pvt *find_call(struct sip_request *req, struct ast_sockaddr *addr, const int intended_method)
 {
@@ -16070,7 +16108,7 @@ static char *sip_show_users(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
 	ast_cli(a->fd, FORMAT, "Username", "Secret", "Accountcode", "Def.Context", "ACL", "ForcerPort");
 
 	user_iter = ao2_iterator_init(peers, 0);
-	while ((user = ao2_iterator_next(&user_iter))) {
+	while ((user = ao2_t_iterator_next(&user_iter, "iterate thru peers table"))) {
 		ao2_lock(user);
 		if (!(user->type & SIP_TYPE_USER)) {
 			ao2_unlock(user);
@@ -16290,7 +16328,7 @@ static char *_sip_show_peers(int fd, int *total, struct mansession *s, const str
 		ao2_lock(peer);
 		if (havepattern && regexec(&regexbuf, peer->name, 0, NULL, 0)) {
 			ao2_unlock(peer);
-			unref_peer(peer, "toss iterator peer ptr before continue");
+			peer = peerarray[k] = unref_peer(peer, "toss iterator peer ptr before continue");
 			continue;
 		}
 
@@ -16362,7 +16400,7 @@ static char *_sip_show_peers(int fd, int *total, struct mansession *s, const str
 			peer->description);
 		}
 		ao2_unlock(peer);
-		unref_peer(peer, "toss iterator peer ptr");
+		peer = peerarray[k] = unref_peer(peer, "toss iterator peer ptr");
 	}
 	
 	if (!s)
@@ -17177,7 +17215,7 @@ static char *complete_sip_user(const char *word, int state)
 	struct sip_peer *user;
 
 	user_iter = ao2_iterator_init(peers, 0);
-	while ((user = ao2_iterator_next(&user_iter))) {
+	while ((user = ao2_t_iterator_next(&user_iter, "iterate thru peers table"))) {
 		ao2_lock(user);
 		if (!(user->type & SIP_TYPE_USER)) {
 			ao2_unlock(user);
@@ -22362,6 +22400,10 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
 			transmit_response(p, "100 Trying", req);
 
 			if (p->t38.state == T38_PEER_REINVITE) {
+				if (p->t38id > -1) {
+					/* reset t38 abort timer */
+					AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "remove ref for t38id"));
+				}
 				p->t38id = ast_sched_add(sched, 5000, sip_t38_abort, dialog_ref(p, "passing dialog ptr into sched structure based on t38id for sip_t38_abort."));
 			} else if (p->t38.state == T38_ENABLED) {
 				ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
@@ -23060,6 +23102,10 @@ static int handle_request_cancel(struct sip_pvt *p, struct sip_request *req)
 			if (pkt->seqno == p->lastinvite && pkt->response_code == 487) {
 				AST_SCHED_DEL(sched, pkt->retransid);
 				UNLINK(pkt, p->packets, prev_pkt);
+				dialog_unref(pkt->owner, "unref packet->owner from dialog");
+				if (pkt->data) {
+					ast_free(pkt->data);
+				}
 				ast_free(pkt);
 				break;
 			}
@@ -24073,6 +24119,10 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req,
 		return 0;
 	}
 
+	/* At this point, if we have an authpeer (which we have to have to get here) we should unref
+	 * it since if we have actually used it, we have reffed it when p->relatedpeer was set. */
+	authpeer = unref_peer(authpeer, "unref pointer into (*authpeer)");
+
 	/* Add subscription for extension state from the PBX core */
 	if (p->subscribed != MWI_NOTIFICATION  && p->subscribed != CALL_COMPLETION && !resubscribe) {
 		if (p->stateid > -1) {
@@ -25077,9 +25127,9 @@ static void restart_session_timer(struct sip_pvt *p)
 	}
 
 	if (p->stimer->st_active == TRUE) {
+		ast_debug(2, "Session timer stopped: %d - %s\n", p->stimer->st_schedid, p->callid);
 		AST_SCHED_DEL_UNREF(sched, p->stimer->st_schedid,
 				dialog_unref(p, "Removing session timer ref"));
-		ast_debug(2, "Session timer stopped: %d - %s\n", p->stimer->st_schedid, p->callid);
 		start_session_timer(p);
 	}
 }
@@ -25095,9 +25145,9 @@ static void stop_session_timer(struct sip_pvt *p)
 
 	if (p->stimer->st_active == TRUE) {
 		p->stimer->st_active = FALSE;
+		ast_debug(2, "Session timer stopped: %d - %s\n", p->stimer->st_schedid, p->callid);
 		AST_SCHED_DEL_UNREF(sched, p->stimer->st_schedid,
 				dialog_unref(p, "removing session timer ref"));
-		ast_debug(2, "Session timer stopped: %d - %s\n", p->stimer->st_schedid, p->callid);
 	}
 }
 
@@ -25110,13 +25160,22 @@ static void start_session_timer(struct sip_pvt *p)
 		return;
 	}
 
-	p->stimer->st_schedid  = ast_sched_add(sched, p->stimer->st_interval * 1000 / 2, proc_session_timer,
+	if (p->stimer->st_schedid > -1) {
+		/* in the event a timer is already going, stop it */
+		ast_debug(2, "Session timer stopped: %d - %s\n", p->stimer->st_schedid, p->callid);
+		AST_SCHED_DEL_UNREF(sched, p->stimer->st_schedid,
+			dialog_unref(p, "unref stimer->st_schedid from dialog"));
+	}
+
+	p->stimer->st_schedid  = ast_sched_add(sched, p->stimer->st_interval * 1000 / 2, proc_session_timer, 
 			dialog_ref(p, "adding session timer ref"));
 	if (p->stimer->st_schedid < 0) {
 		dialog_unref(p, "removing session timer ref");
-		ast_log(LOG_ERROR, "ast_sched_add failed.\n");
+		ast_log(LOG_ERROR, "ast_sched_add failed - %s\n", p->callid);
+	} else {
+		p->stimer->st_active = TRUE;
+		ast_debug(2, "Session timer started: %d - %s\n", p->stimer->st_schedid, p->callid);
 	}
-	ast_debug(2, "Session timer started: %d - %s\n", p->stimer->st_schedid, p->callid);
 }
 
 
@@ -25188,6 +25247,7 @@ return_unref:
 	if (!res) {
 		/* An error occurred.  Stop session timer processing */
 		if (p->stimer) {
+			ast_debug(2, "Session timer stopped: %d - %s\n", p->stimer->st_schedid, p->callid);
 			p->stimer->st_schedid = -1;
 			stop_session_timer(p);
 		}
@@ -25490,7 +25550,8 @@ static int sip_poke_peer(struct sip_peer *peer, int force)
 #endif
 	peer->ps = ast_tvnow();
 	if (xmitres == XMIT_ERROR) {
-		sip_poke_noanswer(peer);	/* Immediately unreachable, network problems */
+		/* Immediately unreachable, network problems */
+		sip_poke_noanswer(ref_peer(peer, "add ref for peerexpire (fake, for sip_poke_noanswer to remove)"));
 	} else if (!force) {
 		AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, peer->maxms * 2, sip_poke_noanswer, peer,
 				unref_peer(_data, "removing poke peer ref"),
@@ -29579,6 +29640,8 @@ static int unload_module(void)
 	}
 	ao2_iterator_destroy(&i);
 
+	unlink_all_peers_from_tables();
+
 	ast_mutex_lock(&monlock);
 	if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
 		pthread_cancel(monitor_thread);
@@ -29630,6 +29693,7 @@ static int unload_module(void)
 	ao2_t_ref(dialogs_needdestroy, -1, "unref the dialogs table");
 	ao2_t_ref(dialogs_rtpcheck, -1, "unref the dialogs table");
 	ao2_t_ref(threadt, -1, "unref the thread table");
+	ao2_t_ref(sip_monitor_instances, -1, "unref the sip_monitor_instances table");
 
 	clear_sip_domains();
 	ast_free_ha(sip_cfg.contact_ha);