diff --git a/include/asterisk/res_pjsip_session.h b/include/asterisk/res_pjsip_session.h
index 10e55f1337c5b90e825a64165c94df894c038a04..e2a90662ed02be5e1b503cfb1aa9319fbaa82bc2 100644
--- a/include/asterisk/res_pjsip_session.h
+++ b/include/asterisk/res_pjsip_session.h
@@ -155,6 +155,10 @@ struct ast_sip_session {
 	struct ast_sip_aor *aor;
 	/*! From header saved at invite creation */
 	pjsip_fromto_hdr *saved_from_hdr;
+	/*! Whether the end of the session should be deferred */
+	unsigned int defer_end:1;
+	/*! Session end (remote hangup) requested while termination deferred */
+	unsigned int ended_while_deferred:1;
 };
 
 typedef int (*ast_sip_session_request_creation_cb)(struct ast_sip_session *session, pjsip_tx_data *tdata);
@@ -483,6 +487,13 @@ int ast_sip_session_defer_termination(struct ast_sip_session *session);
  */
 void ast_sip_session_defer_termination_cancel(struct ast_sip_session *session);
 
+/*!
+ * \brief End the session if it had been previously deferred
+ *
+ * \param session The session to end if it had been deferred
+ */
+void ast_sip_session_end_if_deferred(struct ast_sip_session *session);
+
 /*!
  * \brief Register an SDP handler
  *
diff --git a/res/res_pjsip_refer.c b/res/res_pjsip_refer.c
index 46295387d53cd553e339fdec1776050fa8c76624..456e09dd812e3f93604f1fac18cc7d00f375a811 100644
--- a/res/res_pjsip_refer.c
+++ b/res/res_pjsip_refer.c
@@ -543,6 +543,7 @@ static int refer_attended_task(void *data)
 		}
 	}
 
+	ast_sip_session_end_if_deferred(attended->transferer);
 	if (response != 200) {
 		if (!ast_sip_push_task(attended->transferer->serializer,
 			defer_termination_cancel, attended->transferer)) {
@@ -772,6 +773,7 @@ static int refer_incoming_attended_request(struct ast_sip_session *session, pjsi
 
 		/* Push it to the other session, which will have both channels with minimal locking */
 		if (ast_sip_push_task(other_session->serializer, refer_attended_task, attended)) {
+			ast_sip_session_end_if_deferred(session);
 			ast_sip_session_defer_termination_cancel(session);
 			ao2_cleanup(attended);
 			return 500;
@@ -810,9 +812,12 @@ static int refer_incoming_attended_request(struct ast_sip_session *session, pjsi
 
 		response = xfer_response_code2sip(ast_bridge_transfer_blind(1, session->channel,
 			"external_replaces", context, refer_blind_callback, &refer));
+
+		ast_sip_session_end_if_deferred(session);
 		if (response != 200) {
 			ast_sip_session_defer_termination_cancel(session);
 		}
+
 		return response;
 	}
 }
@@ -865,9 +870,12 @@ static int refer_incoming_blind_request(struct ast_sip_session *session, pjsip_r
 
 	response = xfer_response_code2sip(ast_bridge_transfer_blind(1, session->channel,
 		exten, context, refer_blind_callback, &refer));
+
+	ast_sip_session_end_if_deferred(session);
 	if (response != 200) {
 		ast_sip_session_defer_termination_cancel(session);
 	}
+
 	return response;
 }
 
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index bde66d25adc1a049a2c0f5d93eff9f32092fd2a2..ffd01cadf054ca01156281f8e8f46c3c74fab82b 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -1905,6 +1905,9 @@ int ast_sip_session_defer_termination(struct ast_sip_session *session)
 
 	session->defer_terminate = 1;
 
+	session->defer_end = 1;
+	session->ended_while_deferred = 0;
+
 	session->scheduled_termination.id = 0;
 	ao2_ref(session, +1);
 	session->scheduled_termination.user_data = session;
@@ -1942,6 +1945,7 @@ void ast_sip_session_defer_termination_cancel(struct ast_sip_session *session)
 		/* Already canceled or timer fired. */
 		return;
 	}
+
 	session->defer_terminate = 0;
 
 	if (session->terminate_while_deferred) {
@@ -1953,6 +1957,22 @@ void ast_sip_session_defer_termination_cancel(struct ast_sip_session *session)
 	sip_session_defer_termination_stop_timer(session);
 }
 
+void ast_sip_session_end_if_deferred(struct ast_sip_session *session)
+{
+	if (!session->defer_end) {
+		return;
+	}
+
+	session->defer_end = 0;
+
+	if (session->ended_while_deferred) {
+		/* Complete the session end started by the remote hangup. */
+		ast_debug(3, "Ending session (%p) after being deferred\n", session);
+		session->ended_while_deferred = 0;
+		session_end(session);
+	}
+}
+
 struct ast_sip_session *ast_sip_dialog_get_session(pjsip_dialog *dlg)
 {
 	pjsip_inv_session *inv_session = pjsip_dlg_get_inv_session(dlg);
@@ -2672,6 +2692,12 @@ static void session_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e)
 	}
 
 	if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
+		if (session->defer_end) {
+			ast_debug(3, "Deferring session (%p) end\n", session);
+			session->ended_while_deferred = 1;
+			return;
+		}
+
 		if (ast_sip_push_task(session->serializer, session_end, session)) {
 			/* Do it anyway even though this is not the right thread. */
 			session_end(session);
diff --git a/res/res_pjsip_session.exports.in b/res/res_pjsip_session.exports.in
index a39485e66d2a01f9b7f6493f84963986ca9aa015..fdfc5fb4724615c568bf91985299bc34519a7ec3 100644
--- a/res/res_pjsip_session.exports.in
+++ b/res/res_pjsip_session.exports.in
@@ -3,6 +3,7 @@
 		LINKER_SYMBOL_PREFIXast_sip_session_terminate;
 		LINKER_SYMBOL_PREFIXast_sip_session_defer_termination;
 		LINKER_SYMBOL_PREFIXast_sip_session_defer_termination_cancel;
+		LINKER_SYMBOL_PREFIXast_sip_session_end_if_deferred;
 		LINKER_SYMBOL_PREFIXast_sip_session_register_sdp_handler;
 		LINKER_SYMBOL_PREFIXast_sip_session_unregister_sdp_handler;
 		LINKER_SYMBOL_PREFIXast_sip_session_register_supplement;