]> git.pld-linux.org Git - packages/pjproject.git/blame - 0002-r5435-add-pjsip_inv_session-ref_cnt.patch
Patches and config_site.h updates from Asterisk 13.12
[packages/pjproject.git] / 0002-r5435-add-pjsip_inv_session-ref_cnt.patch
CommitLineData
14efab78
JK
1When a transport error occured on an INVITE session
2the stack calls on_tsx_state_changed with new state
3PJSIP_INV_STATE_DISCONNECTED and immediately destroys
4the INVITE session.
5At the same time this INVITE session could being processed
6on another thread. This thread could use the session's
7memory pools which were already freed, so we get segfault.
8
9This patch adds a reference counter and new functions:
10pjsip_inv_add_ref and pjsip_inv_dec_ref.
11The INVITE session is destroyed only when the reference
12counter has reached zero.
13
14To avoid race condition an application should call
15pjsip_inv_add_ref/pjsip_inv_dec_ref.
16
17Index: pjsip/include/pjsip-ua/sip_inv.h
18===================================================================
19--- a/pjsip/include/pjsip-ua/sip_inv.h (revision 5434)
20+++ b/pjsip/include/pjsip-ua/sip_inv.h (revision 5435)
21@@ -383,6 +383,11 @@
22 * Other applications that want to use these pools must understand
23 * that the flip-flop pool's lifetimes are synchronized to the
24 * SDP offer-answer negotiation.
25+ *
26+ * The lifetime of this session is controlled by the reference counter in this
27+ * structure, which is manipulated by calling #pjsip_inv_add_ref and
28+ * #pjsip_inv_dec_ref. When the reference counter has reached zero, then
29+ * this session will be destroyed.
30 */
31 struct pjsip_inv_session
32 {
33@@ -412,6 +417,7 @@
34 struct pjsip_timer *timer; /**< Session Timers. */
35 pj_bool_t following_fork; /**< Internal, following
36 forked media? */
37+ pj_atomic_t *ref_cnt; /**< Reference counter. */
38 };
39
40
41@@ -631,6 +637,30 @@
42
43
44 /**
45+ * Add reference counter to the INVITE session. The reference counter controls
46+ * the life time of the session, ie. when the counter reaches zero, then it
47+ * will be destroyed.
48+ *
49+ * @param inv The INVITE session.
50+ * @return PJ_SUCCESS if the INVITE session reference counter
51+ * was increased.
52+ */
53+PJ_DECL(pj_status_t) pjsip_inv_add_ref( pjsip_inv_session *inv );
54+
55+/**
56+ * Decrement reference counter of the INVITE session.
57+ * When the session is no longer used, it will be destroyed and
58+ * caller is informed with PJ_EGONE return status.
59+ *
60+ * @param inv The INVITE session.
61+ * @return PJ_SUCCESS if the INVITE session reference counter
62+ * was decreased. A status PJ_EGONE will be returned to
63+ * inform that session is destroyed.
64+ */
65+PJ_DECL(pj_status_t) pjsip_inv_dec_ref( pjsip_inv_session *inv );
66+
67+
68+/**
69 * Forcefully terminate and destroy INVITE session, regardless of
70 * the state of the session. Note that this function should only be used
71 * when there is failure in the INVITE session creation. After the
72Index: pjsip/src/pjsip-ua/sip_inv.c
73===================================================================
74--- a/pjsip/src/pjsip-ua/sip_inv.c (revision 5434)
75+++ b/pjsip/src/pjsip-ua/sip_inv.c (revision 5435)
76@@ -195,6 +195,65 @@
77 }
78
79 /*
80+ * Add reference to INVITE session.
81+ */
82+PJ_DEF(pj_status_t) pjsip_inv_add_ref( pjsip_inv_session *inv )
83+{
84+ PJ_ASSERT_RETURN(inv && inv->ref_cnt, PJ_EINVAL);
85+
86+ pj_atomic_inc(inv->ref_cnt);
87+
88+ return PJ_SUCCESS;
89+}
90+
91+static void inv_session_destroy(pjsip_inv_session *inv)
92+{
93+ if (inv->last_ack) {
94+ pjsip_tx_data_dec_ref(inv->last_ack);
95+ inv->last_ack = NULL;
96+ }
97+ if (inv->invite_req) {
98+ pjsip_tx_data_dec_ref(inv->invite_req);
99+ inv->invite_req = NULL;
100+ }
101+ if (inv->pending_bye) {
102+ pjsip_tx_data_dec_ref(inv->pending_bye);
103+ inv->pending_bye = NULL;
104+ }
105+ pjsip_100rel_end_session(inv);
106+ pjsip_timer_end_session(inv);
107+ pjsip_dlg_dec_session(inv->dlg, &mod_inv.mod);
108+
109+ /* Release the flip-flop pools */
110+ pj_pool_release(inv->pool_prov);
111+ inv->pool_prov = NULL;
112+ pj_pool_release(inv->pool_active);
113+ inv->pool_active = NULL;
114+
115+ pj_atomic_destroy(inv->ref_cnt);
116+ inv->ref_cnt = NULL;
117+}
118+
119+/*
120+ * Decrease INVITE session reference, destroy it when the reference count
121+ * reaches zero.
122+ */
123+PJ_DEF(pj_status_t) pjsip_inv_dec_ref( pjsip_inv_session *inv )
124+{
125+ pj_atomic_value_t ref_cnt;
126+
127+ PJ_ASSERT_RETURN(inv && inv->ref_cnt, PJ_EINVAL);
128+
129+ ref_cnt = pj_atomic_dec_and_get(inv->ref_cnt);
130+ pj_assert( ref_cnt >= 0);
131+ if (ref_cnt == 0) {
132+ inv_session_destroy(inv);
133+ return PJ_EGONE;
134+ }
135+ return PJ_SUCCESS;
136+}
137+
138+/*
139 * Set session state.
140 */
141 static void inv_set_state(pjsip_inv_session *inv, pjsip_inv_state state,
142@@ -261,27 +320,7 @@
143 if (inv->state == PJSIP_INV_STATE_DISCONNECTED &&
144 prev_state != PJSIP_INV_STATE_DISCONNECTED)
145 {
146- if (inv->last_ack) {
147- pjsip_tx_data_dec_ref(inv->last_ack);
148- inv->last_ack = NULL;
149- }
150- if (inv->invite_req) {
151- pjsip_tx_data_dec_ref(inv->invite_req);
152- inv->invite_req = NULL;
153- }
154- if (inv->pending_bye) {
155- pjsip_tx_data_dec_ref(inv->pending_bye);
156- inv->pending_bye = NULL;
157- }
158- pjsip_100rel_end_session(inv);
159- pjsip_timer_end_session(inv);
160- pjsip_dlg_dec_session(inv->dlg, &mod_inv.mod);
161-
162- /* Release the flip-flop pools */
163- pj_pool_release(inv->pool_prov);
164- inv->pool_prov = NULL;
165- pj_pool_release(inv->pool_active);
166- inv->pool_active = NULL;
167+ pjsip_inv_dec_ref(inv);
168 }
169 }
170
171@@ -838,6 +877,12 @@
172 inv = PJ_POOL_ZALLOC_T(dlg->pool, pjsip_inv_session);
173 pj_assert(inv != NULL);
174
175+ status = pj_atomic_create(dlg->pool, 0, &inv->ref_cnt);
176+ if (status != PJ_SUCCESS) {
177+ pjsip_dlg_dec_lock(dlg);
178+ return status;
179+ }
180+
181 inv->pool = dlg->pool;
182 inv->role = PJSIP_ROLE_UAC;
183 inv->state = PJSIP_INV_STATE_NULL;
184@@ -881,6 +926,7 @@
185 pjsip_100rel_attach(inv);
186
187 /* Done */
188+ pjsip_inv_add_ref(inv);
189 *p_inv = inv;
190
191 pjsip_dlg_dec_lock(dlg);
192@@ -1471,6 +1517,12 @@
193 inv = PJ_POOL_ZALLOC_T(dlg->pool, pjsip_inv_session);
194 pj_assert(inv != NULL);
195
196+ status = pj_atomic_create(dlg->pool, 0, &inv->ref_cnt);
197+ if (status != PJ_SUCCESS) {
198+ pjsip_dlg_dec_lock(dlg);
199+ return status;
200+ }
201+
202 inv->pool = dlg->pool;
203 inv->role = PJSIP_ROLE_UAS;
204 inv->state = PJSIP_INV_STATE_NULL;
205@@ -1540,6 +1592,7 @@
206 }
207
208 /* Done */
209+ pjsip_inv_add_ref(inv);
210 pjsip_dlg_dec_lock(dlg);
211 *p_inv = inv;
212
This page took 0.136467 seconds and 4 git commands to generate.