diff options
author | Benny Prijono <bennylp@teluu.com> | 2010-01-25 13:42:56 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2010-01-25 13:42:56 +0000 |
commit | 31f597e11a1547e0ce2932b02183f8807a6c6722 (patch) | |
tree | 69ee18cf67fda25a88f1da66cc07839823e393fa | |
parent | bee900b43985446ad579a2642a68ae2461dd2964 (diff) |
Initial commit for #1033: Assertion error when shutting down PJSIP while TCP/TLS connect is in progress and a transaction is waiting
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3071 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r-- | pjsip/include/pjsip/sip_transaction.h | 5 | ||||
-rw-r--r-- | pjsip/include/pjsip/sip_transport.h | 4 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_transaction.c | 66 |
3 files changed, 61 insertions, 14 deletions
diff --git a/pjsip/include/pjsip/sip_transaction.h b/pjsip/include/pjsip/sip_transaction.h index eb8510ae..febc53c9 100644 --- a/pjsip/include/pjsip/sip_transaction.h +++ b/pjsip/include/pjsip/sip_transaction.h @@ -97,7 +97,6 @@ struct pjsip_transaction pj_str_t transaction_key;/**< Hash table key. */ pj_uint32_t hashed_key; /**< Key's hashed value. */ pj_str_t branch; /**< The branch Id. */ - pjsip_tpselector tp_sel; /**< Transport selector. */ /* * State and status. @@ -121,6 +120,10 @@ struct pjsip_transaction pjsip_response_addr res_addr; /**< Response address. */ unsigned transport_flag; /**< Miscelaneous flag. */ pj_status_t transport_err; /**< Internal error code. */ + pjsip_tpselector tp_sel; /**< Transport selector. */ + pjsip_tx_data *pending_tx; /**< Tdata which caused + pending transport flag + to be set on tsx. */ /* * Messages and timer. diff --git a/pjsip/include/pjsip/sip_transport.h b/pjsip/include/pjsip/sip_transport.h index b971762f..04c5255c 100644 --- a/pjsip/include/pjsip/sip_transport.h +++ b/pjsip/include/pjsip/sip_transport.h @@ -569,6 +569,10 @@ struct pjsip_tx_data */ pjsip_tpselector tp_sel; + /** + * Arbitrary data attached by PJSIP modules. + */ + void *mod_data[PJSIP_MAX_MODULE]; }; diff --git a/pjsip/src/pjsip/sip_transaction.c b/pjsip/src/pjsip/sip_transaction.c index d5be2b97..026220a2 100644 --- a/pjsip/src/pjsip/sip_transaction.c +++ b/pjsip/src/pjsip/sip_transaction.c @@ -581,6 +581,15 @@ static pj_status_t mod_tsx_layer_register_tsx( pjsip_transaction *tsx) */ static void mod_tsx_layer_unregister_tsx( pjsip_transaction *tsx) { + if (mod_tsx_layer.mod.id == -1) { + /* The transaction layer has been unregistered. This could happen + * if the transaction was pending on transport and the application + * is shutdown. See http://trac.pjsip.org/repos/ticket/1033. In + * this case just do nothing. + */ + return; + } + pj_assert(tsx->transaction_key.slen != 0); //pj_assert(tsx->state != PJSIP_TSX_STATE_NULL); @@ -1115,21 +1124,28 @@ static void tsx_set_state( pjsip_transaction *tsx, if (state == PJSIP_TSX_STATE_TERMINATED) { pj_time_val timeout = {0, 0}; - /* Reschedule timeout timer to destroy this transaction. */ + /* If we're still waiting for a message to be sent.. */ if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { - tsx->transport_flag |= TSX_HAS_PENDING_DESTROY; - } else { - /* Cancel timeout timer. */ - if (tsx->timeout_timer.id != 0) { - pjsip_endpt_cancel_timer(tsx->endpt, &tsx->timeout_timer); - tsx->timeout_timer.id = 0; - } + /* Disassociate ourselves from the outstanding transmit data + * so that when the send callback is called we will be able + * to ignore that (otherwise we'll get assertion, see + * http://trac.pjsip.org/repos/ticket/1033) + */ + tsx->pending_tx->mod_data[mod_tsx_layer.mod.id] = NULL; + tsx->pending_tx = NULL; + tsx->transport_flag &= ~(TSX_HAS_PENDING_TRANSPORT); + } - tsx->timeout_timer.id = TIMER_ACTIVE; - pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, - &timeout); + /* Cancel timeout timer. */ + if (tsx->timeout_timer.id != 0) { + pjsip_endpt_cancel_timer(tsx->endpt, &tsx->timeout_timer); + tsx->timeout_timer.id = 0; } + tsx->timeout_timer.id = TIMER_ACTIVE; + pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, + &timeout); + } else if (state == PJSIP_TSX_STATE_DESTROYED) { @@ -1637,6 +1653,17 @@ static void send_msg_callback( pjsip_send_state *send_state, pjsip_tx_data *tdata = send_state->tdata; struct tsx_lock_data lck; + /* Check if transaction has cancelled itself from this transmit + * notification (https://trac.pjsip.org/repos/ticket/1033). + */ + if (tdata->mod_data[mod_tsx_layer.mod.id] == NULL) { + return; + } + + /* Reset */ + tdata->mod_data[mod_tsx_layer.mod.id] = NULL; + tsx->pending_tx = NULL; + lock_tsx(tsx, &lck); if (sent > 0) { @@ -1906,6 +1933,13 @@ static pj_status_t tsx_send_msg( pjsip_transaction *tsx, */ pjsip_tx_data_add_ref(tdata); + /* Also attach ourselves to the transmit data so that we'll be able + * to unregister ourselves from the send notification of this + * transmit data. + */ + tdata->mod_data[mod_tsx_layer.mod.id] = tsx; + tsx->pending_tx = tdata; + /* Begin resolving destination etc to send the message. */ if (tdata->msg->type == PJSIP_REQUEST_MSG) { @@ -1914,8 +1948,11 @@ static pj_status_t tsx_send_msg( pjsip_transaction *tsx, &send_msg_callback); if (status == PJ_EPENDING) status = PJ_SUCCESS; - if (status != PJ_SUCCESS) + if (status != PJ_SUCCESS) { pjsip_tx_data_dec_ref(tdata); + tdata->mod_data[mod_tsx_layer.mod.id] = NULL; + tsx->pending_tx = NULL; + } /* Check if transaction is terminated. */ if (status==PJ_SUCCESS && tsx->state == PJSIP_TSX_STATE_TERMINATED) @@ -1929,8 +1966,11 @@ static pj_status_t tsx_send_msg( pjsip_transaction *tsx, &send_msg_callback); if (status == PJ_EPENDING) status = PJ_SUCCESS; - if (status != PJ_SUCCESS) + if (status != PJ_SUCCESS) { pjsip_tx_data_dec_ref(tdata); + tdata->mod_data[mod_tsx_layer.mod.id] = NULL; + tsx->pending_tx = NULL; + } /* Check if transaction is terminated. */ if (status==PJ_SUCCESS && tsx->state == PJSIP_TSX_STATE_TERMINATED) |