[Asterisk-code-review] res pjsip session: segfault on already disconnected session (asterisk[master])

Anonymous Coward asteriskteam at digium.com
Wed Sep 7 14:41:28 CDT 2016


Anonymous Coward #1000019 has submitted this change and it was merged.

Change subject: res_pjsip_session: segfault on already disconnected session
......................................................................


res_pjsip_session: segfault on already disconnected session

On heavy loaded system the TCP/TLS incoming calls could be
disconnected by pjproject while these calls are being
processed by asterisk which could use the session's memory pools.
If the session in the disconnected state then the session memory
pools were already freed, so we get segfault.

This patch adds a lifetime control on an INVITE session to pjproject.
The lifetime of the session is manipulated by calling
pjsip_inv_add_ref/pjsip_inv_dec_ref.
This patch uses these functions to inform pjproject that the
session is in use.

This patch adds check if the session state is not disconnected
and also checks if the memory pool is not NULL.

This patch also places tasks 'session_end' and 'session_end_completion'
into session's serializer to avoid race condition.

ASTERISK-26291 #close

Change-Id: I4d28b1fb3b91f0492a911d110049d670fdc3c8d7
---
M configure
M configure.ac
M include/asterisk/autoconfig.h.in
M res/res_pjsip_session.c
M third-party/pjproject/configure.m4
A third-party/pjproject/patches/0002-r5435-add-pjsip_inv_session-ref_cnt.patch
6 files changed, 403 insertions(+), 9 deletions(-)

Approvals:
  George Joseph: Looks good to me, but someone else must approve
  Anonymous Coward #1000019: Verified
  Joshua Colp: Looks good to me, approved



diff --git a/configure b/configure
index 3e5140d..886ef6f 100755
--- a/configure
+++ b/configure
@@ -935,6 +935,10 @@
 POPT_DIR
 POPT_INCLUDE
 POPT_LIB
+PBX_PJSIP_INV_SESSION_REF
+PJSIP_INV_SESSION_REF_DIR
+PJSIP_INV_SESSION_REF_INCLUDE
+PJSIP_INV_SESSION_REF_LIB
 PBX_PJSIP_EVSUB_GRP_LOCK
 PJSIP_EVSUB_GRP_LOCK_DIR
 PJSIP_EVSUB_GRP_LOCK_INCLUDE
@@ -10994,6 +10998,18 @@
 PJSIP_EVSUB_GRP_LOCK_DIR=${PJPROJECT_DIR}
 
 PBX_PJSIP_EVSUB_GRP_LOCK=0
+
+
+
+
+
+
+
+PJSIP_INV_SESSION_REF_DESCRIP="PJSIP INVITE Session Reference Count support"
+PJSIP_INV_SESSION_REF_OPTION=pjsip
+PJSIP_INV_SESSION_REF_DIR=${PJPROJECT_DIR}
+
+PBX_PJSIP_INV_SESSION_REF=0
 
 
 
@@ -25269,6 +25285,9 @@
 $as_echo "#define HAVE_PJSIP_EVSUB_GRP_LOCK 1" >>confdefs.h
 
 
+$as_echo "#define HAVE_PJSIP_INV_SESSION_REF 1" >>confdefs.h
+
+
    else
 
    if test "x${PBX_PJPROJECT}" != "x1" -a "${USE_PJPROJECT}" != "no"; then
@@ -26089,6 +26108,110 @@
 fi
 
 
+
+if test "x${PBX_PJSIP_INV_SESSION_REF}" != "x1" -a "${USE_PJSIP_INV_SESSION_REF}" != "no"; then
+   pbxlibdir=""
+   # if --with-PJSIP_INV_SESSION_REF=DIR has been specified, use it.
+   if test "x${PJSIP_INV_SESSION_REF_DIR}" != "x"; then
+      if test -d ${PJSIP_INV_SESSION_REF_DIR}/lib; then
+         pbxlibdir="-L${PJSIP_INV_SESSION_REF_DIR}/lib"
+      else
+         pbxlibdir="-L${PJSIP_INV_SESSION_REF_DIR}"
+      fi
+   fi
+   pbxfuncname="pjsip_inv_add_ref"
+   if test "x${pbxfuncname}" = "x" ; then   # empty lib, assume only headers
+      AST_PJSIP_INV_SESSION_REF_FOUND=yes
+   else
+      ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
+      CFLAGS="${CFLAGS} $PJPROJECT_CFLAGS"
+      as_ac_Lib=`$as_echo "ac_cv_lib_pjsip_${pbxfuncname}" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpjsip" >&5
+$as_echo_n "checking for ${pbxfuncname} in -lpjsip... " >&6; }
+if eval \${$as_ac_Lib+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpjsip ${pbxlibdir} $PJPROJECT_LIB $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ${pbxfuncname} ();
+int
+main ()
+{
+return ${pbxfuncname} ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$as_ac_Lib=yes"
+else
+  eval "$as_ac_Lib=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+eval ac_res=\$$as_ac_Lib
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then :
+  AST_PJSIP_INV_SESSION_REF_FOUND=yes
+else
+  AST_PJSIP_INV_SESSION_REF_FOUND=no
+fi
+
+      CFLAGS="${ast_ext_lib_check_save_CFLAGS}"
+   fi
+
+   # now check for the header.
+   if test "${AST_PJSIP_INV_SESSION_REF_FOUND}" = "yes"; then
+      PJSIP_INV_SESSION_REF_LIB="${pbxlibdir} -lpjsip $PJPROJECT_LIB"
+      # if --with-PJSIP_INV_SESSION_REF=DIR has been specified, use it.
+      if test "x${PJSIP_INV_SESSION_REF_DIR}" != "x"; then
+         PJSIP_INV_SESSION_REF_INCLUDE="-I${PJSIP_INV_SESSION_REF_DIR}/include"
+      fi
+      PJSIP_INV_SESSION_REF_INCLUDE="${PJSIP_INV_SESSION_REF_INCLUDE} $PJPROJECT_CFLAGS"
+      if test "xpjsip.h" = "x" ; then	# no header, assume found
+         PJSIP_INV_SESSION_REF_HEADER_FOUND="1"
+      else				# check for the header
+         ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}"
+         CPPFLAGS="${CPPFLAGS} ${PJSIP_INV_SESSION_REF_INCLUDE}"
+         ac_fn_c_check_header_mongrel "$LINENO" "pjsip.h" "ac_cv_header_pjsip_h" "$ac_includes_default"
+if test "x$ac_cv_header_pjsip_h" = xyes; then :
+  PJSIP_INV_SESSION_REF_HEADER_FOUND=1
+else
+  PJSIP_INV_SESSION_REF_HEADER_FOUND=0
+fi
+
+
+         CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}"
+      fi
+      if test "x${PJSIP_INV_SESSION_REF_HEADER_FOUND}" = "x0" ; then
+         PJSIP_INV_SESSION_REF_LIB=""
+         PJSIP_INV_SESSION_REF_INCLUDE=""
+      else
+         if test "x${pbxfuncname}" = "x" ; then		# only checking headers -> no library
+            PJSIP_INV_SESSION_REF_LIB=""
+         fi
+         PBX_PJSIP_INV_SESSION_REF=1
+         cat >>confdefs.h <<_ACEOF
+#define HAVE_PJSIP_INV_SESSION_REF 1
+_ACEOF
+
+      fi
+   fi
+fi
+
+
    fi
 fi
 
diff --git a/configure.ac b/configure.ac
index 950cfc5..7fd702f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -487,6 +487,7 @@
 AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_EXTERNAL_RESOLVER], [PJSIP External Resolver Support], [PJPROJECT], [pjsip])
 AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_TLS_TRANSPORT_PROTO], [PJSIP TLS Transport proto field support], [PJPROJECT], [pjsip])
 AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_EVSUB_GRP_LOCK], [PJSIP EVSUB Group Lock support], [PJPROJECT], [pjsip])
+AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_INV_SESSION_REF], [PJSIP INVITE Session Reference Count support], [PJPROJECT], [pjsip])
 
 AST_EXT_LIB_SETUP([POPT], [popt], [popt])
 AST_EXT_LIB_SETUP([PORTAUDIO], [PortAudio], [portaudio])
@@ -2210,6 +2211,7 @@
       CPPFLAGS="${saved_cppflags}"
 
       AST_EXT_LIB_CHECK([PJSIP_EVSUB_GRP_LOCK], [pjsip], [pjsip_evsub_add_ref], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
+      AST_EXT_LIB_CHECK([PJSIP_INV_SESSION_REF], [pjsip], [pjsip_inv_add_ref], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
    fi
 fi
 
diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in
index f9a6b46..5e7ea7e 100644
--- a/include/asterisk/autoconfig.h.in
+++ b/include/asterisk/autoconfig.h.in
@@ -598,6 +598,9 @@
 /* Define if your system has pjsip_get_dest_info declared. */
 #undef HAVE_PJSIP_GET_DEST_INFO
 
+/* Define if your system has PJSIP_INV_SESSION_REF */
+#undef HAVE_PJSIP_INV_SESSION_REF
+
 /* Define if your system has the PJSIP_REPLACE_MEDIA_STREAM headers. */
 #undef HAVE_PJSIP_REPLACE_MEDIA_STREAM
 
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 315393f..f54ee94 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -213,6 +213,11 @@
 	int i;
 	int handled = 0;
 
+	if (session->inv_session && session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
+		ast_log(LOG_ERROR, "Failed to handle incoming SDP. Session has been already disconnected\n");
+		return -1;
+	}
+
 	for (i = 0; i < sdp->media_count; ++i) {
 		/* See if there are registered handlers for this media stream type */
 		char media[20];
@@ -2087,6 +2092,16 @@
 	 * so that we will be notified so we can destroy the session properly
 	 */
 
+	if (invite->session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
+		ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
+			invite->session->inv_session->cause,
+			pjsip_get_status_text(invite->session->inv_session->cause)->ptr);
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+		pjsip_inv_dec_ref(invite->session->inv_session);
+#endif
+		return -1;
+	}
+
 	switch (get_destination(invite->session, invite->rdata)) {
 	case SIP_GET_DEST_EXTEN_FOUND:
 		/* Things worked. Keep going */
@@ -2097,7 +2112,7 @@
 		} else  {
 			pjsip_inv_terminate(invite->session->inv_session, 416, PJ_TRUE);
 		}
-		return 0;
+		goto end;
 	case SIP_GET_DEST_EXTEN_NOT_FOUND:
 	case SIP_GET_DEST_EXTEN_PARTIAL:
 	default:
@@ -2110,7 +2125,7 @@
 		} else  {
 			pjsip_inv_terminate(invite->session->inv_session, 404, PJ_TRUE);
 		}
-		return 0;
+		goto end;
 	};
 
 	if ((sdp_info = pjsip_rdata_get_sdp_info(invite->rdata)) && (sdp_info->sdp_err == PJ_SUCCESS) && sdp_info->sdp) {
@@ -2120,7 +2135,7 @@
 			} else  {
 				pjsip_inv_terminate(invite->session->inv_session, 488, PJ_TRUE);
 			}
-			return 0;
+			goto end;
 		}
 		/* We are creating a local SDP which is an answer to their offer */
 		local = create_local_sdp(invite->session->inv_session, invite->session, sdp_info->sdp);
@@ -2136,7 +2151,7 @@
 		} else  {
 			pjsip_inv_terminate(invite->session->inv_session, 500, PJ_TRUE);
 		}
-		return 0;
+		goto end;
 	} else {
 		pjsip_inv_set_local_sdp(invite->session->inv_session, local);
 		pjmedia_sdp_neg_set_prefer_remote_codec_order(invite->session->inv_session->neg, PJ_FALSE);
@@ -2153,12 +2168,16 @@
 	/* At this point, we've verified what we can, so let's go ahead and send a 100 Trying out */
 	if (pjsip_inv_initial_answer(invite->session->inv_session, invite->rdata, 100, NULL, NULL, &tdata) != PJ_SUCCESS) {
 		pjsip_inv_terminate(invite->session->inv_session, 500, PJ_TRUE);
-		return 0;
+		goto end;
 	}
 	ast_sip_session_send_response(invite->session, tdata);
 
 	handle_incoming_request(invite->session, invite->rdata);
 
+end:
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+	pjsip_inv_dec_ref(invite->session->inv_session);
+#endif
 	return 0;
 }
 
@@ -2179,6 +2198,20 @@
 		return;
 	}
 
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+	if (pjsip_inv_add_ref(inv_session) != PJ_SUCCESS) {
+		ast_log(LOG_ERROR, "Can't increase the session reference counter\n");
+		if (inv_session->state != PJSIP_INV_STATE_DISCONNECTED) {
+			if (pjsip_inv_initial_answer(inv_session, rdata, 500, NULL, NULL, &tdata) == PJ_SUCCESS) {
+				pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
+			} else {
+				internal_pjsip_inv_send_msg(inv_session, endpoint->transport, tdata);
+			}
+		}
+		return;
+	}
+#endif
+
 	session = ast_sip_session_alloc(endpoint, NULL, inv_session, rdata);
 	if (!session) {
 		if (pjsip_inv_initial_answer(inv_session, rdata, 500, NULL, NULL, &tdata) == PJ_SUCCESS) {
@@ -2186,6 +2219,9 @@
 		} else {
 			internal_pjsip_inv_send_msg(inv_session, endpoint->transport, tdata);
 		}
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+		pjsip_inv_dec_ref(inv_session);
+#endif
 		return;
 	}
 
@@ -2196,6 +2232,9 @@
 		} else {
 			internal_pjsip_inv_send_msg(inv_session, endpoint->transport, tdata);
 		}
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+		pjsip_inv_dec_ref(inv_session);
+#endif
 		ao2_cleanup(invite);
 	}
 	ao2_ref(session, -1);
@@ -2467,8 +2506,9 @@
 	}
 }
 
-static void session_end(struct ast_sip_session *session)
+static int session_end(void *vsession)
 {
+	struct ast_sip_session *session = vsession;
 	struct ast_sip_session_supplement *iter;
 
 	/* Stop the scheduled termination */
@@ -2480,6 +2520,7 @@
 			iter->session_end(session);
 		}
 	}
+	return 0;
 }
 
 /*!
@@ -2617,7 +2658,10 @@
 	}
 
 	if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
-		session_end(session);
+		if (ast_sip_push_task(session->serializer, session_end, session)) {
+			/* Do it anyway even though this is not the right thread. */
+			session_end(session);
+		}
 	}
 }
 
@@ -2784,7 +2828,11 @@
 			 * Pass the session ref held by session->inv_session to
 			 * session_end_completion().
 			 */
-			session_end_completion(session);
+			if (session
+				&& ast_sip_push_task(session->serializer, session_end_completion, session)) {
+				/* Do it anyway even though this is not the right thread. */
+				session_end_completion(session);
+			}
 			return;
 		}
 		break;
@@ -2909,7 +2957,12 @@
 	static const pj_str_t STR_IP6 = { "IP6", 3 };
 	pjmedia_sdp_session *local;
 
-	if (!(local = PJ_POOL_ZALLOC_T(inv->pool_prov, pjmedia_sdp_session))) {
+	if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
+		ast_log(LOG_ERROR, "Failed to create session SDP. Session has been already disconnected\n");
+		return NULL;
+	}
+
+	if (!inv->pool_prov || !(local = PJ_POOL_ZALLOC_T(inv->pool_prov, pjmedia_sdp_session))) {
 		return NULL;
 	}
 
diff --git a/third-party/pjproject/configure.m4 b/third-party/pjproject/configure.m4
index 67ac04d..7a079f6 100644
--- a/third-party/pjproject/configure.m4
+++ b/third-party/pjproject/configure.m4
@@ -45,4 +45,5 @@
 	PJPROJECT_SYMBOL_CHECK([PJSIP_EXTERNAL_RESOLVER], [pjsip_endpt_set_ext_resolver], [pjsip.h])
 	AC_DEFINE([HAVE_PJSIP_TLS_TRANSPORT_PROTO], 1, [Define if your system has PJSIP_TLS_TRANSPORT_PROTO])
 	AC_DEFINE([HAVE_PJSIP_EVSUB_GRP_LOCK], 1, [Define if your system has PJSIP_EVSUB_GRP_LOCK])
+	AC_DEFINE([HAVE_PJSIP_INV_SESSION_REF], 1, [Define if your system has PJSIP_INV_SESSION_REF])
 ])
diff --git a/third-party/pjproject/patches/0002-r5435-add-pjsip_inv_session-ref_cnt.patch b/third-party/pjproject/patches/0002-r5435-add-pjsip_inv_session-ref_cnt.patch
new file mode 100644
index 0000000..12ae6a0
--- /dev/null
+++ b/third-party/pjproject/patches/0002-r5435-add-pjsip_inv_session-ref_cnt.patch
@@ -0,0 +1,212 @@
+When a transport error occured on an INVITE session
+the stack calls on_tsx_state_changed with new state
+PJSIP_INV_STATE_DISCONNECTED and immediately destroys
+the INVITE session.
+At the same time this INVITE session could being processed
+on another thread. This thread could use the session's
+memory pools which were already freed, so we get segfault.
+
+This patch adds a reference counter and new functions:
+pjsip_inv_add_ref and pjsip_inv_dec_ref.
+The INVITE session is destroyed only when the reference
+counter has reached zero.
+
+To avoid race condition an application should call
+pjsip_inv_add_ref/pjsip_inv_dec_ref.
+
+Index: pjsip/include/pjsip-ua/sip_inv.h
+===================================================================
+--- a/pjsip/include/pjsip-ua/sip_inv.h	(revision 5434)
++++ b/pjsip/include/pjsip-ua/sip_inv.h	(revision 5435)
+@@ -383,6 +383,11 @@
+  * Other applications that want to use these pools must understand
+  * that the flip-flop pool's lifetimes are synchronized to the
+  * SDP offer-answer negotiation.
++ *
++ * The lifetime of this session is controlled by the reference counter in this
++ * structure, which is manipulated by calling #pjsip_inv_add_ref and
++ * #pjsip_inv_dec_ref. When the reference counter has reached zero, then
++ * this session will be destroyed.
+  */
+ struct pjsip_inv_session
+ {
+@@ -412,6 +417,7 @@
+     struct pjsip_timer	*timer;			    /**< Session Timers.    */
+     pj_bool_t		 following_fork;	    /**< Internal, following
+ 							 forked media?	    */
++    pj_atomic_t		*ref_cnt;		    /**< Reference counter. */
+ };
+ 
+ 
+@@ -631,6 +637,30 @@
+ 
+ 
+ /**
++ * Add reference counter to the INVITE session. The reference counter controls
++ * the life time of the session, ie. when the counter reaches zero, then it 
++ * will be destroyed.
++ *
++ * @param inv       The INVITE session.
++ * @return          PJ_SUCCESS if the INVITE session reference counter
++ *                  was increased.
++ */
++PJ_DECL(pj_status_t) pjsip_inv_add_ref( pjsip_inv_session *inv );
++
++/**
++ * Decrement reference counter of the INVITE session.
++ * When the session is no longer used, it will be destroyed and
++ * caller is informed with PJ_EGONE return status.
++ *
++ * @param inv       The INVITE session.
++ * @return          PJ_SUCCESS if the INVITE session reference counter
++ *                  was decreased. A status PJ_EGONE will be returned to 
++ *                  inform that session is destroyed.
++ */
++PJ_DECL(pj_status_t) pjsip_inv_dec_ref( pjsip_inv_session *inv );
++
++
++/**
+  * Forcefully terminate and destroy INVITE session, regardless of
+  * the state of the session. Note that this function should only be used
+  * when there is failure in the INVITE session creation. After the
+Index: pjsip/src/pjsip-ua/sip_inv.c
+===================================================================
+--- a/pjsip/src/pjsip-ua/sip_inv.c	(revision 5434)
++++ b/pjsip/src/pjsip-ua/sip_inv.c	(revision 5435)
+@@ -195,6 +195,65 @@
+ }
+ 
+ /*
++ * Add reference to INVITE session.
++ */
++PJ_DEF(pj_status_t) pjsip_inv_add_ref( pjsip_inv_session *inv )
++{
++    PJ_ASSERT_RETURN(inv && inv->ref_cnt, PJ_EINVAL);
++
++    pj_atomic_inc(inv->ref_cnt);
++
++    return PJ_SUCCESS;
++}
++
++static void inv_session_destroy(pjsip_inv_session *inv)
++{
++    if (inv->last_ack) {
++	pjsip_tx_data_dec_ref(inv->last_ack);
++	inv->last_ack = NULL;
++    }
++    if (inv->invite_req) {
++	pjsip_tx_data_dec_ref(inv->invite_req);
++	inv->invite_req = NULL;
++    }
++    if (inv->pending_bye) {
++	pjsip_tx_data_dec_ref(inv->pending_bye);
++	inv->pending_bye = NULL;
++    }
++    pjsip_100rel_end_session(inv);
++    pjsip_timer_end_session(inv);
++    pjsip_dlg_dec_session(inv->dlg, &mod_inv.mod);
++
++    /* Release the flip-flop pools */
++    pj_pool_release(inv->pool_prov);
++    inv->pool_prov = NULL;
++    pj_pool_release(inv->pool_active);
++    inv->pool_active = NULL;
++
++    pj_atomic_destroy(inv->ref_cnt);
++    inv->ref_cnt = NULL;
++}
++
++/*
++ * Decrease INVITE session reference, destroy it when the reference count
++ * reaches zero.
++ */
++PJ_DEF(pj_status_t) pjsip_inv_dec_ref( pjsip_inv_session *inv )
++{
++    pj_atomic_value_t ref_cnt;
++
++    PJ_ASSERT_RETURN(inv && inv->ref_cnt, PJ_EINVAL);
++
++    ref_cnt = pj_atomic_dec_and_get(inv->ref_cnt);
++    pj_assert( ref_cnt >= 0);
++    if (ref_cnt == 0) {
++        inv_session_destroy(inv);
++        return PJ_EGONE;
++    } 
++    return PJ_SUCCESS;    
++}
++
++/*
+  * Set session state.
+  */
+ static void inv_set_state(pjsip_inv_session *inv, pjsip_inv_state state,
+@@ -261,27 +320,7 @@
+     if (inv->state == PJSIP_INV_STATE_DISCONNECTED &&
+ 	prev_state != PJSIP_INV_STATE_DISCONNECTED) 
+     {
+-	if (inv->last_ack) {
+-	    pjsip_tx_data_dec_ref(inv->last_ack);
+-	    inv->last_ack = NULL;
+-	}
+-	if (inv->invite_req) {
+-	    pjsip_tx_data_dec_ref(inv->invite_req);
+-	    inv->invite_req = NULL;
+-	}
+-	if (inv->pending_bye) {
+-	    pjsip_tx_data_dec_ref(inv->pending_bye);
+-	    inv->pending_bye = NULL;
+-	}
+-	pjsip_100rel_end_session(inv);
+-	pjsip_timer_end_session(inv);
+-	pjsip_dlg_dec_session(inv->dlg, &mod_inv.mod);
+-
+-	/* Release the flip-flop pools */
+-	pj_pool_release(inv->pool_prov);
+-	inv->pool_prov = NULL;
+-	pj_pool_release(inv->pool_active);
+-	inv->pool_active = NULL;
++	pjsip_inv_dec_ref(inv);
+     }
+ }
+ 
+@@ -838,6 +877,12 @@
+     inv = PJ_POOL_ZALLOC_T(dlg->pool, pjsip_inv_session);
+     pj_assert(inv != NULL);
+ 
++    status = pj_atomic_create(dlg->pool, 0, &inv->ref_cnt);
++    if (status != PJ_SUCCESS) {
++	pjsip_dlg_dec_lock(dlg);
++	return status;
++    }
++
+     inv->pool = dlg->pool;
+     inv->role = PJSIP_ROLE_UAC;
+     inv->state = PJSIP_INV_STATE_NULL;
+@@ -881,6 +926,7 @@
+     pjsip_100rel_attach(inv);
+ 
+     /* Done */
++    pjsip_inv_add_ref(inv);
+     *p_inv = inv;
+ 
+     pjsip_dlg_dec_lock(dlg);
+@@ -1471,6 +1517,12 @@
+     inv = PJ_POOL_ZALLOC_T(dlg->pool, pjsip_inv_session);
+     pj_assert(inv != NULL);
+ 
++    status = pj_atomic_create(dlg->pool, 0, &inv->ref_cnt);
++    if (status != PJ_SUCCESS) {
++	pjsip_dlg_dec_lock(dlg);
++	return status;
++    }
++
+     inv->pool = dlg->pool;
+     inv->role = PJSIP_ROLE_UAS;
+     inv->state = PJSIP_INV_STATE_NULL;
+@@ -1540,6 +1592,7 @@
+     }
+ 
+     /* Done */
++    pjsip_inv_add_ref(inv);
+     pjsip_dlg_dec_lock(dlg);
+     *p_inv = inv;
+ 

-- 
To view, visit https://gerrit.asterisk.org/3833
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I4d28b1fb3b91f0492a911d110049d670fdc3c8d7
Gerrit-PatchSet: 1
Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Owner: Alexei Gradinari <alex2grad at gmail.com>
Gerrit-Reviewer: Anonymous Coward #1000019
Gerrit-Reviewer: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>



More information about the asterisk-code-review mailing list