summaryrefslogtreecommitdiff
path: root/third-party
diff options
context:
space:
mode:
authorzuul <zuul@gerrit.asterisk.org>2016-09-07 14:04:26 -0500
committerGerrit Code Review <gerrit2@gerrit.digium.api>2016-09-07 14:04:26 -0500
commit892536729188c29aecb6b2b5a6bab8928a63f530 (patch)
tree56c258d7f982dd3b7f96a4a19cb926fc03cdf7fc /third-party
parent4b66c74c9422c10c25dd42c7d204c5f499749d80 (diff)
parent9bca89546992a540d106a725734e6038cb91d76f (diff)
Merge "res_pjsip_session: segfault on already disconnected session" into 13
Diffstat (limited to 'third-party')
-rw-r--r--third-party/pjproject/configure.m41
-rw-r--r--third-party/pjproject/patches/0002-r5435-add-pjsip_inv_session-ref_cnt.patch212
2 files changed, 213 insertions, 0 deletions
diff --git a/third-party/pjproject/configure.m4 b/third-party/pjproject/configure.m4
index 67ac04d4d..7a079f657 100644
--- a/third-party/pjproject/configure.m4
+++ b/third-party/pjproject/configure.m4
@@ -45,4 +45,5 @@ AC_DEFUN([PJPROJECT_CONFIGURE],
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 000000000..12ae6a028
--- /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;
+