diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index e81796af56292a8e4e2e2a8b0a305b9aef58df35..4dc4e33e4d371977087a700173e6e244ff76b458 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -3815,9 +3815,20 @@ static int __sip_autodestruct(const void *data)
 
 	/* If there are packets still waiting for delivery, delay the destruction */
 	if (p->packets) {
-		ast_debug(3, "Re-scheduled destruction of SIP call %s\n", p->callid ? p->callid : "<unknown>");
-		append_history(p, "ReliableXmit", "timeout");
-		return 10000;
+		if (!p->needdestroy) {
+			char method_str[30];
+			ast_debug(3, "Re-scheduled destruction of SIP call %s\n", p->callid ? p->callid : "<unknown>");
+			append_history(p, "ReliableXmit", "timeout");
+			if (sscanf(p->lastmsg, "Tx: %s", method_str) == 1 || sscanf(p->lastmsg, "Rx: %s", method_str) == 1) {
+				if (method_match(SIP_CANCEL, method_str) || method_match(SIP_BYE, method_str)) {
+					pvt_set_needdestroy(p, "autodestruct");
+				}
+			}
+			return 10000;
+		} else {
+			/* They've had their chance to respond. Time to bail */
+			__sip_pretend_ack(p);
+		}
 	}
 
 	if (p->subscribed == MWI_NOTIFICATION)
@@ -3879,7 +3890,7 @@ static int sip_cancel_destroy(struct sip_pvt *p)
 	int res = 0;
 	if (p->autokillid > -1) {
 		int res3;
-		
+
 		if (!(res3 = ast_sched_del(sched, p->autokillid))) {
 			append_history(p, "CancelDestroy", "");
 			p->autokillid = -1;
@@ -6026,7 +6037,10 @@ static int sip_hangup(struct ast_channel *ast)
 		if (needcancel) {	/* Outgoing call, not up */
 			if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
 				/* stop retransmitting an INVITE that has not received a response */
-				__sip_pretend_ack(p);
+				struct sip_pkt *cur;
+				for (cur = p->packets; cur; cur = cur->next) {
+					__sip_semi_ack(p, cur->seqno, cur->is_resp, cur->method ? cur->method : find_sip_method(cur->data->str));
+				}
 
 				/* if we can't send right now, mark it pending */
 				if (p->invitestate == INV_CALLING) {