Fixed #1671:
- Transport manager maintains transmit buffer instance list, so any dangling transmit buffer will be freed when transport manager is destroyed. This is configurable via PJSIP_HAS_TX_DATA_LIST, the default is zero/disabled. - Updated publish client subscription to not use the 'internal' pjsip_tx_data list structure. git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@4530 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
parent
1483dcd38f
commit
9b63b68ec1
|
@ -1132,6 +1132,21 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void)
|
|||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Specify whether transport manager should maintain a list of transmit
|
||||
* buffer instances, so any possible dangling instance can be cleaned up
|
||||
* when the transport manager is shutdown (see also ticket #1671).
|
||||
* Note that this feature will have slight impact on the performance as
|
||||
* mutex is employed in updating the list, i.e: on creation and destruction
|
||||
* of transmit data.
|
||||
*
|
||||
* Default: 0 (no)
|
||||
*/
|
||||
#ifndef PJSIP_HAS_TX_DATA_LIST
|
||||
# define PJSIP_HAS_TX_DATA_LIST 0
|
||||
#endif
|
||||
|
||||
|
||||
PJ_END_DECL
|
||||
|
||||
/**
|
||||
|
|
|
@ -61,7 +61,8 @@ const pjsip_method pjsip_publish_method =
|
|||
*/
|
||||
typedef struct pending_publish
|
||||
{
|
||||
PJ_DECL_LIST_MEMBER(pjsip_tx_data);
|
||||
PJ_DECL_LIST_MEMBER(struct pending_publish);
|
||||
pjsip_tx_data *tdata;
|
||||
} pending_publish;
|
||||
|
||||
|
||||
|
@ -108,6 +109,7 @@ struct pjsip_publishc
|
|||
|
||||
/* Pending PUBLISH request */
|
||||
pending_publish pending_reqs;
|
||||
pending_publish pending_reqs_empty;
|
||||
};
|
||||
|
||||
|
||||
|
@ -180,6 +182,7 @@ PJ_DEF(pj_status_t) pjsip_publishc_create( pjsip_endpoint *endpt,
|
|||
}
|
||||
pj_memcpy(&pubc->opt, opt, sizeof(*opt));
|
||||
pj_list_init(&pubc->pending_reqs);
|
||||
pj_list_init(&pubc->pending_reqs_empty);
|
||||
|
||||
status = pj_mutex_create_recursive(pubc->pool, "pubc%p", &pubc->mutex);
|
||||
if (status != PJ_SUCCESS) {
|
||||
|
@ -683,8 +686,14 @@ static void tsx_callback(void *token, pjsip_event *event)
|
|||
/* If we have pending request(s), send them now */
|
||||
pj_mutex_lock(pubc->mutex);
|
||||
while (!pj_list_empty(&pubc->pending_reqs)) {
|
||||
pjsip_tx_data *tdata = pubc->pending_reqs.next;
|
||||
pj_list_erase(tdata);
|
||||
pending_publish *pp = pubc->pending_reqs.next;
|
||||
pjsip_tx_data *tdata = pp->tdata;
|
||||
|
||||
/* Remove the request from pending request list,
|
||||
* and keep the unused entry into pending_reqs_empty pool.
|
||||
*/
|
||||
pj_list_erase(pp);
|
||||
pj_list_push_back(&pubc->pending_reqs_empty, pp);
|
||||
|
||||
/* Add SIP-If-Match if we have etag and the request doesn't have
|
||||
* one (http://trac.pjsip.org/repos/ticket/996)
|
||||
|
@ -712,7 +721,6 @@ static void tsx_callback(void *token, pjsip_event *event)
|
|||
status = pjsip_publishc_send(pubc, tdata);
|
||||
if (status == PJ_EPENDING) {
|
||||
pj_assert(!"Not expected");
|
||||
pj_list_erase(tdata);
|
||||
pjsip_tx_data_dec_ref(tdata);
|
||||
} else if (status == PJ_SUCCESS) {
|
||||
break;
|
||||
|
@ -744,7 +752,15 @@ PJ_DEF(pj_status_t) pjsip_publishc_send(pjsip_publishc *pubc,
|
|||
pj_mutex_lock(pubc->mutex);
|
||||
if (pubc->pending_tsx) {
|
||||
if (pubc->opt.queue_request) {
|
||||
pj_list_push_back(&pubc->pending_reqs, tdata);
|
||||
pending_publish *pp = NULL;
|
||||
if (pj_list_empty(&pubc->pending_reqs_empty)) {
|
||||
pp = PJ_POOL_ZALLOC_T(pubc->pool, pending_publish);
|
||||
} else {
|
||||
pp = pubc->pending_reqs_empty.next;
|
||||
pj_list_erase(pp);
|
||||
}
|
||||
pp->tdata = tdata;
|
||||
pj_list_push_back(&pubc->pending_reqs, pp);
|
||||
pj_mutex_unlock(pubc->mutex);
|
||||
PJ_LOG(4,(THIS_FILE, "Request is queued, pubc has another "
|
||||
"transaction pending"));
|
||||
|
|
|
@ -92,6 +92,11 @@ struct pjsip_tpmgr
|
|||
void (*on_rx_msg)(pjsip_endpoint*, pj_status_t, pjsip_rx_data*);
|
||||
pj_status_t (*on_tx_msg)(pjsip_endpoint*, pjsip_tx_data*);
|
||||
pjsip_tp_state_callback tp_state_cb;
|
||||
|
||||
/* Transmit data list, for transmit data cleanup when transport manager
|
||||
* is destroyed.
|
||||
*/
|
||||
pjsip_tx_data tdata_list;
|
||||
};
|
||||
|
||||
|
||||
|
@ -419,6 +424,14 @@ PJ_DEF(pj_status_t) pjsip_tx_data_create( pjsip_tpmgr *mgr,
|
|||
}
|
||||
|
||||
pj_ioqueue_op_key_init(&tdata->op_key.key, sizeof(tdata->op_key.key));
|
||||
pj_list_init(tdata);
|
||||
|
||||
#if defined(PJSIP_HAS_TX_DATA_LIST) && PJSIP_HAS_TX_DATA_LIST!=0
|
||||
/* Append this just created tdata to transmit buffer list */
|
||||
pj_lock_acquire(mgr->lock);
|
||||
pj_list_push_back(&mgr->tdata_list, tdata);
|
||||
pj_lock_release(mgr->lock);
|
||||
#endif
|
||||
|
||||
#if defined(PJ_DEBUG) && PJ_DEBUG!=0
|
||||
pj_atomic_inc( tdata->mgr->tdata_counter );
|
||||
|
@ -437,6 +450,27 @@ PJ_DEF(void) pjsip_tx_data_add_ref( pjsip_tx_data *tdata )
|
|||
pj_atomic_inc(tdata->ref_cnt);
|
||||
}
|
||||
|
||||
static void tx_data_destroy(pjsip_tx_data *tdata)
|
||||
{
|
||||
PJ_LOG(5,(tdata->obj_name, "Destroying txdata %s",
|
||||
pjsip_tx_data_get_info(tdata)));
|
||||
pjsip_tpselector_dec_ref(&tdata->tp_sel);
|
||||
#if defined(PJ_DEBUG) && PJ_DEBUG!=0
|
||||
pj_atomic_dec( tdata->mgr->tdata_counter );
|
||||
#endif
|
||||
|
||||
#if defined(PJSIP_HAS_TX_DATA_LIST) && PJSIP_HAS_TX_DATA_LIST!=0
|
||||
/* Remove this tdata from transmit buffer list */
|
||||
pj_lock_acquire(tdata->mgr->lock);
|
||||
pj_list_erase(tdata);
|
||||
pj_lock_release(tdata->mgr->lock);
|
||||
#endif
|
||||
|
||||
pj_atomic_destroy( tdata->ref_cnt );
|
||||
pj_lock_destroy( tdata->lock );
|
||||
pjsip_endpt_release_pool( tdata->mgr->endpt, tdata->pool );
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrease transport data reference, destroy it when the reference count
|
||||
* reaches zero.
|
||||
|
@ -445,15 +479,7 @@ PJ_DEF(pj_status_t) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata )
|
|||
{
|
||||
pj_assert( pj_atomic_get(tdata->ref_cnt) > 0);
|
||||
if (pj_atomic_dec_and_get(tdata->ref_cnt) <= 0) {
|
||||
PJ_LOG(5,(tdata->obj_name, "Destroying txdata %s",
|
||||
pjsip_tx_data_get_info(tdata)));
|
||||
pjsip_tpselector_dec_ref(&tdata->tp_sel);
|
||||
#if defined(PJ_DEBUG) && PJ_DEBUG!=0
|
||||
pj_atomic_dec( tdata->mgr->tdata_counter );
|
||||
#endif
|
||||
pj_atomic_destroy( tdata->ref_cnt );
|
||||
pj_lock_destroy( tdata->lock );
|
||||
pjsip_endpt_release_pool( tdata->mgr->endpt, tdata->pool );
|
||||
tx_data_destroy(tdata);
|
||||
return PJSIP_EBUFDESTROYED;
|
||||
} else {
|
||||
return PJ_SUCCESS;
|
||||
|
@ -1207,6 +1233,7 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_create( pj_pool_t *pool,
|
|||
mgr->on_rx_msg = rx_cb;
|
||||
mgr->on_tx_msg = tx_cb;
|
||||
pj_list_init(&mgr->factory_list);
|
||||
pj_list_init(&mgr->tdata_list);
|
||||
|
||||
mgr->table = pj_hash_create(pool, PJSIP_TPMGR_HTABLE_SIZE);
|
||||
if (!mgr->table)
|
||||
|
@ -1497,12 +1524,6 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_destroy( pjsip_tpmgr *mgr )
|
|||
}
|
||||
|
||||
pj_lock_release(mgr->lock);
|
||||
pj_lock_destroy(mgr->lock);
|
||||
|
||||
/* Unregister mod_msg_print. */
|
||||
if (mod_msg_print.id != -1) {
|
||||
pjsip_endpt_unregister_module(endpt, &mod_msg_print);
|
||||
}
|
||||
|
||||
#if defined(PJ_DEBUG) && PJ_DEBUG!=0
|
||||
/* If you encounter assert error on this line, it means there are
|
||||
|
@ -1518,6 +1539,26 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_destroy( pjsip_tpmgr *mgr )
|
|||
pj_atomic_destroy(mgr->tdata_counter);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Destroy any dangling transmit buffer.
|
||||
*/
|
||||
if (!pj_list_empty(&mgr->tdata_list)) {
|
||||
pjsip_tx_data *tdata = mgr->tdata_list.next;
|
||||
while (tdata != &mgr->tdata_list) {
|
||||
pjsip_tx_data *next = tdata->next;
|
||||
tx_data_destroy(tdata);
|
||||
tdata = next;
|
||||
}
|
||||
PJ_LOG(3,(THIS_FILE, "Cleaned up dangling transmit buffer(s)."));
|
||||
}
|
||||
|
||||
pj_lock_destroy(mgr->lock);
|
||||
|
||||
/* Unregister mod_msg_print. */
|
||||
if (mod_msg_print.id != -1) {
|
||||
pjsip_endpt_unregister_module(endpt, &mod_msg_print);
|
||||
}
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue