Author: mmichelson Date: Fri Nov 14 08:21:55 2014 New Revision: 427840 URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=427840 Log: Fix a possible race condition where duplicate requests may be handled by separate threads.
If an endpoint retransmits a request, it's possible due to temporary load that Asterisk may end up processing both requests at the same time in separate threads. One thread will successfully handle the request, while the other thread fails to handle the request since the first thread already registered the transaction with the PJSIP core. The fix here is to detect the duplicated transaction failure and to silently absorb the request since another thread should be properly handling the request. Review: https://reviewboard.asterisk.org/r/4175 Modified: branches/12/include/asterisk/res_pjsip.h branches/12/res/res_pjsip.c branches/12/res/res_pjsip_pubsub.c branches/12/res/res_pjsip_session.c Modified: branches/12/include/asterisk/res_pjsip.h URL: http://svnview.digium.com/svn/asterisk/branches/12/include/asterisk/res_pjsip.h?view=diff&rev=427840&r1=427839&r2=427840 ============================================================================== --- branches/12/include/asterisk/res_pjsip.h (original) +++ branches/12/include/asterisk/res_pjsip.h Fri Nov 14 08:21:55 2014 @@ -1228,8 +1228,9 @@ * * \param endpoint A pointer to the endpoint * \param rdata The request that is starting the dialog - */ -pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata); + * \param[out] status On failure, the reason for failure in creating the dialog + */ +pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status); /*! * \brief General purpose method for creating an rdata structure using specific information Modified: branches/12/res/res_pjsip.c URL: http://svnview.digium.com/svn/asterisk/branches/12/res/res_pjsip.c?view=diff&rev=427840&r1=427839&r2=427840 ============================================================================== --- branches/12/res/res_pjsip.c (original) +++ branches/12/res/res_pjsip.c Fri Nov 14 08:21:55 2014 @@ -1646,12 +1646,13 @@ return dlg; } -pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata) +pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status) { pjsip_dialog *dlg; pj_str_t contact; pjsip_transport_type_e type = rdata->tp_info.transport->key.type; - pj_status_t status; + + ast_assert(status != NULL); contact.ptr = pj_pool_alloc(rdata->tp_info.pool, PJSIP_MAX_URL_SIZE); contact.slen = pj_ansi_snprintf(contact.ptr, PJSIP_MAX_URL_SIZE, @@ -1664,11 +1665,11 @@ (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "", (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : ""); - status = pjsip_dlg_create_uas(pjsip_ua_instance(), rdata, &contact, &dlg); - if (status != PJ_SUCCESS) { + *status = pjsip_dlg_create_uas(pjsip_ua_instance(), rdata, &contact, &dlg); + if (*status != PJ_SUCCESS) { char err[PJ_ERR_MSG_SIZE]; - pj_strerror(status, err, sizeof(err)); + pj_strerror(*status, err, sizeof(err)); ast_log(LOG_ERROR, "Could not create dialog with endpoint %s. %s\n", ast_sorcery_object_get_id(endpoint), err); return NULL; Modified: branches/12/res/res_pjsip_pubsub.c URL: http://svnview.digium.com/svn/asterisk/branches/12/res/res_pjsip_pubsub.c?view=diff&rev=427840&r1=427839&r2=427840 ============================================================================== --- branches/12/res/res_pjsip_pubsub.c (original) +++ branches/12/res/res_pjsip_pubsub.c Fri Nov 14 08:21:55 2014 @@ -122,6 +122,7 @@ #define MOD_DATA_BODY_GENERATOR "sub_body_generator" #define MOD_DATA_PERSISTENCE "sub_persistence" +#define MOD_DATA_DLG_STATUS "dlg_status" static const pj_str_t str_event_name = { "Event", 5 }; @@ -721,6 +722,7 @@ struct ast_sip_subscription *sub = ao2_alloc(sizeof(*sub), subscription_destructor); pjsip_dialog *dlg; struct subscription_persistence *persistence; + pj_status_t dlg_status; if (!sub) { return NULL; @@ -739,7 +741,9 @@ pubsub_module.id, MOD_DATA_BODY_GENERATOR); sub->role = role; if (role == AST_SIP_NOTIFIER) { - dlg = ast_sip_create_dialog_uas(endpoint, rdata); + dlg = ast_sip_create_dialog_uas(endpoint, rdata, &dlg_status); + ast_sip_mod_data_set(rdata->tp_info.pool, rdata->endpt_info.mod_data, + pubsub_module.id, MOD_DATA_DLG_STATUS, (void *) dlg_status); } else { RAII_VAR(struct ast_sip_contact *, contact, NULL, ao2_cleanup); @@ -1173,7 +1177,10 @@ } pjsip_dlg_send_response(dlg, trans, tdata); } else { - pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL); + long dlg_status = (long) ast_sip_mod_data_get(rdata->endpt_info.mod_data, pubsub_module.id, MOD_DATA_DLG_STATUS); + if (dlg_status != PJ_EEXISTS) { + pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL); + } } } else { sub->persistence = subscription_persistence_create(sub); Modified: branches/12/res/res_pjsip_session.c URL: http://svnview.digium.com/svn/asterisk/branches/12/res/res_pjsip_session.c?view=diff&rev=427840&r1=427839&r2=427840 ============================================================================== --- branches/12/res/res_pjsip_session.c (original) +++ branches/12/res/res_pjsip_session.c Fri Nov 14 08:21:55 2014 @@ -1406,6 +1406,7 @@ pjsip_dialog *dlg; pjsip_inv_session *inv_session; unsigned int options = endpoint->extensions.flags; + pj_status_t dlg_status; if (pjsip_inv_verify_request(rdata, &options, NULL, NULL, ast_sip_get_pjsip_endpoint(), &tdata) != PJ_SUCCESS) { if (tdata) { @@ -1415,9 +1416,11 @@ } return NULL; } - dlg = ast_sip_create_dialog_uas(endpoint, rdata); + dlg = ast_sip_create_dialog_uas(endpoint, rdata, &dlg_status); if (!dlg) { - pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL); + if (dlg_status != PJ_EEXISTS) { + pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL); + } return NULL; } if (pjsip_inv_create_uas(dlg, rdata, NULL, options, &inv_session) != PJ_SUCCESS) { -- _____________________________________________________________________ -- Bandwidth and Colocation Provided by http://www.api-digital.com -- svn-commits mailing list To UNSUBSCRIBE or update options visit: http://lists.digium.com/mailman/listinfo/svn-commits
