res_pjsip: Move URI validation to use time.

In a realtime based system with a limited number of threadpool threads
it is possible for a deadlock to occur. This happens when permanent
endpoint state is updated, which will cause database queries to be done.
These queries may result in URI validation being done which is done
synchronously using a PJSIP thread. If all PJSIP threads are in use
processing traffic they themselves may be blocked waiting to get the
permanent endpoint container lock when identifying an endpoint.

This change moves URI validation to occur at use time instead of
configuration time. While this comes at a cost of not seeing a problem
until you use it it does solve the underlying deadlock problem.

ASTERISK-25486 #close

Change-Id: I2d7d167af987d23b3e8199e4a68f3359eba4c76a
This commit is contained in:
Joshua Colp
2015-10-21 13:44:17 -03:00
parent 7c560a9a31
commit f2725c8b77
4 changed files with 22 additions and 63 deletions

View File

@@ -1084,29 +1084,6 @@ static struct ast_endpoint *persistent_endpoint_find_or_create(const struct ast_
return persistent->endpoint;
}
/*! \brief Helper function which validates an outbound proxy */
static int outbound_proxy_validate(void *data)
{
const char *proxy = data;
pj_pool_t *pool;
pj_str_t tmp;
static const pj_str_t ROUTE_HNAME = { "Route", 5 };
pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "Outbound Proxy Validation", 256, 256);
if (!pool) {
return -1;
}
pj_strdup2_with_null(pool, &tmp, proxy);
if (!pjsip_parse_hdr(pool, &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL)) {
pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
return -1;
}
pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
return 0;
}
/*! \brief Callback function for when an object is finalized */
static int sip_endpoint_apply_handler(const struct ast_sorcery *sorcery, void *obj)
{
@@ -1116,12 +1093,7 @@ static int sip_endpoint_apply_handler(const struct ast_sorcery *sorcery, void *o
return -1;
}
if (!ast_strlen_zero(endpoint->outbound_proxy) &&
ast_sip_push_task_synchronous(NULL, outbound_proxy_validate, (char*)endpoint->outbound_proxy)) {
ast_log(LOG_ERROR, "Invalid outbound proxy '%s' specified on endpoint '%s'\n",
endpoint->outbound_proxy, ast_sorcery_object_get_id(endpoint));
return -1;
} else if (endpoint->extensions.timer.min_se < 90) {
if (endpoint->extensions.timer.min_se < 90) {
ast_log(LOG_ERROR, "Session timer minimum expires time must be 90 or greater on endpoint '%s'\n",
ast_sorcery_object_get_id(endpoint));
return -1;