summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiong Sauw Ming <ming@teluu.com>2014-06-26 10:39:35 +0000
committerLiong Sauw Ming <ming@teluu.com>2014-06-26 10:39:35 +0000
commit62c44dfdba4ae551cb9e167401b3b80cfeeaaa51 (patch)
tree68de538d4b3660e1cb3a764c95cc0a4f65e727f3
parent7050f951b13f1c6d66af8d2d295e1a22b8fb4ca3 (diff)
Fixed #1774: Unfreed transports upon stack shutdown/restart
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4865 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjsip/src/pjsip/sip_transport.c54
1 files changed, 51 insertions, 3 deletions
diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c
index 66e5d1bb..fd97d614 100644
--- a/pjsip/src/pjsip/sip_transport.c
+++ b/pjsip/src/pjsip/sip_transport.c
@@ -77,6 +77,13 @@ static pjsip_module mod_msg_print =
NULL, /* on_tsx_state() */
};
+/* Transport list item */
+typedef struct transport
+{
+ PJ_DECL_LIST_MEMBER(struct transport);
+ pjsip_transport *tp;
+} transport;
+
/*
* Transport manager.
*/
@@ -97,6 +104,12 @@ struct pjsip_tpmgr
* is destroyed.
*/
pjsip_tx_data tdata_list;
+
+ /* List of transports which are NOT stored in the hash table, so
+ * that it can be properly cleaned up when transport manager
+ * is destroyed.
+ */
+ transport tp_list;
};
@@ -1027,8 +1040,19 @@ PJ_DEF(pj_status_t) pjsip_transport_register( pjsip_tpmgr *mgr,
/* If entry already occupied, unregister previous entry */
hval = 0;
entry = pj_hash_get(mgr->table, &tp->key, key_len, &hval);
- if (entry != NULL)
+ if (entry != NULL) {
+ transport *tp_ref;
+
+ tp_ref = PJ_POOL_ZALLOC_T(((pjsip_transport *)entry)->pool, transport);
+
+ /*
+ * Add transport to the list before removing it from the hash table.
+ * See ticket #1774 for more details.
+ */
+ tp_ref->tp = (pjsip_transport *)entry;
+ pj_list_push_back(&mgr->tp_list, tp_ref);
pj_hash_set(NULL, mgr->table, &tp->key, key_len, hval, NULL);
+ }
/* Register new entry */
pj_hash_set(tp->pool, mgr->table, &tp->key, key_len, hval, tp);
@@ -1074,8 +1098,19 @@ static pj_status_t destroy_transport( pjsip_tpmgr *mgr,
key_len = sizeof(tp->key.type) + tp->addr_len;
hval = 0;
entry = pj_hash_get(mgr->table, &tp->key, key_len, &hval);
- if (entry == (void*)tp)
+ if (entry == (void*)tp) {
pj_hash_set(NULL, mgr->table, &tp->key, key_len, hval, NULL);
+ } else {
+ /* If not found in hash table, remove from the tranport list. */
+ transport *tp_iter = mgr->tp_list.next;
+ while (tp_iter != &mgr->tp_list) {
+ if (tp_iter->tp == tp) {
+ pj_list_erase(tp_iter);
+ break;
+ }
+ tp_iter = tp_iter->next;
+ }
+ }
pj_lock_release(mgr->lock);
@@ -1258,6 +1293,7 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_create( pj_pool_t *pool,
mgr->on_tx_msg = tx_cb;
pj_list_init(&mgr->factory_list);
pj_list_init(&mgr->tdata_list);
+ pj_list_init(&mgr->tp_list);
mgr->table = pj_hash_create(pool, PJSIP_TPMGR_HTABLE_SIZE);
if (!mgr->table)
@@ -1526,7 +1562,7 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_destroy( pjsip_tpmgr *mgr )
pj_lock_acquire(mgr->lock);
/*
- * Destroy all transports.
+ * Destroy all transports in the hash table.
*/
itr = pj_hash_first(mgr->table, &itr_val);
while (itr != NULL) {
@@ -1543,6 +1579,18 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_destroy( pjsip_tpmgr *mgr )
}
/*
+ * Destroy transports in the list.
+ */
+ if (!pj_list_empty(&mgr->tp_list)) {
+ transport *tp_iter = mgr->tp_list.next;
+ while (tp_iter != &mgr->tp_list) {
+ transport *next = tp_iter->next;
+ destroy_transport(mgr, tp_iter->tp);
+ tp_iter = next;
+ }
+ }
+
+ /*
* Destroy all factories/listeners.
*/
factory = mgr->factory_list.next;