Merge "res_pjsip: Fix deadlock on reliable transport shutdown." into 13

certified/13.21
Jenkins2 7 years ago committed by Gerrit Code Review
commit b3cec9d445

@ -835,6 +835,8 @@ static int reregister_immediately_cb(void *obj)
* *
* \param obj What is needed to initiate a reregister attempt. * \param obj What is needed to initiate a reregister attempt.
* *
* \note Normally executed by the pjsip monitor thread.
*
* \return Nothing * \return Nothing
*/ */
static void registration_transport_shutdown_cb(void *obj) static void registration_transport_shutdown_cb(void *obj)

@ -560,15 +560,52 @@ static void *publication_resource_alloc(const char *name)
return ast_sorcery_generic_alloc(sizeof(struct ast_sip_publication_resource), publication_resource_destroy); return ast_sorcery_generic_alloc(sizeof(struct ast_sip_publication_resource), publication_resource_destroy);
} }
static void sub_tree_transport_cb(void *data) { static int sub_tree_subscription_terminate_cb(void *data)
{
struct sip_subscription_tree *sub_tree = data; struct sip_subscription_tree *sub_tree = data;
ast_debug(3, "Transport destroyed. Removing subscription '%s->%s' prune on restart: %d\n", if (!sub_tree->evsub) {
/* Something else already terminated the subscription. */
ao2_ref(sub_tree, -1);
return 0;
}
ast_debug(3, "Transport destroyed. Removing subscription '%s->%s' prune on boot: %d\n",
sub_tree->persistence->endpoint, sub_tree->root->resource, sub_tree->persistence->endpoint, sub_tree->root->resource,
sub_tree->persistence->prune_on_boot); sub_tree->persistence->prune_on_boot);
sub_tree->state = SIP_SUB_TREE_TERMINATE_IN_PROGRESS; sub_tree->state = SIP_SUB_TREE_TERMINATE_IN_PROGRESS;
pjsip_evsub_terminate(sub_tree->evsub, PJ_TRUE); pjsip_evsub_terminate(sub_tree->evsub, PJ_TRUE);
ao2_ref(sub_tree, -1);
return 0;
}
/*!
* \internal
* \brief The reliable transport we used as a subscription contact has shutdown.
*
* \param data What subscription needs to be terminated.
*
* \note Normally executed by the pjsip monitor thread.
*
* \return Nothing
*/
static void sub_tree_transport_cb(void *data)
{
struct sip_subscription_tree *sub_tree = data;
/*
* Push off the subscription termination to the serializer to
* avoid deadlock. Another thread could be trying to send a
* message on the subscription that can deadlock with this
* thread.
*/
ao2_ref(sub_tree, +1);
if (ast_sip_push_task(sub_tree->serializer, sub_tree_subscription_terminate_cb,
sub_tree)) {
ao2_ref(sub_tree, -1);
}
} }
/*! \brief Destructor for subscription persistence */ /*! \brief Destructor for subscription persistence */
@ -621,7 +658,7 @@ static void subscription_persistence_update(struct sip_subscription_tree *sub_tr
return; return;
} }
ast_debug(3, "Updating persistence for '%s->%s' prune on restart: %s\n", ast_debug(3, "Updating persistence for '%s->%s' prune on boot: %s\n",
sub_tree->persistence->endpoint, sub_tree->root->resource, sub_tree->persistence->endpoint, sub_tree->root->resource,
sub_tree->persistence->prune_on_boot ? "yes" : "no"); sub_tree->persistence->prune_on_boot ? "yes" : "no");
@ -645,7 +682,7 @@ static void subscription_persistence_update(struct sip_subscription_tree *sub_tr
sub_tree->endpoint, rdata); sub_tree->endpoint, rdata);
if (sub_tree->persistence->prune_on_boot) { if (sub_tree->persistence->prune_on_boot) {
ast_debug(3, "adding transport monitor on %s for '%s->%s' prune on restart: %d\n", ast_debug(3, "adding transport monitor on %s for '%s->%s' prune on boot: %d\n",
rdata->tp_info.transport->obj_name, rdata->tp_info.transport->obj_name,
sub_tree->persistence->endpoint, sub_tree->root->resource, sub_tree->persistence->endpoint, sub_tree->root->resource,
sub_tree->persistence->prune_on_boot); sub_tree->persistence->prune_on_boot);

@ -337,7 +337,7 @@ static int contact_transport_monitor_matcher(void *a, void *b)
&& strcmp(ma->contact_name, mb->contact_name) == 0; && strcmp(ma->contact_name, mb->contact_name) == 0;
} }
static void register_contact_transport_shutdown_cb(void *data) static int register_contact_transport_remove_cb(void *data)
{ {
struct contact_transport_monitor *monitor = data; struct contact_transport_monitor *monitor = data;
struct ast_sip_contact *contact; struct ast_sip_contact *contact;
@ -345,7 +345,8 @@ static void register_contact_transport_shutdown_cb(void *data)
lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_MUTEX, "aor", monitor->aor_name); lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_MUTEX, "aor", monitor->aor_name);
if (!lock) { if (!lock) {
return; ao2_ref(monitor, -1);
return 0;
} }
ao2_lock(lock); ao2_lock(lock);
@ -365,6 +366,35 @@ static void register_contact_transport_shutdown_cb(void *data)
} }
ao2_unlock(lock); ao2_unlock(lock);
ast_named_lock_put(lock); ast_named_lock_put(lock);
ao2_ref(monitor, -1);
return 0;
}
/*!
* \internal
* \brief The reliable transport we registered as a contact has shutdown.
*
* \param data What contact needs to be removed.
*
* \note Normally executed by the pjsip monitor thread.
*
* \return Nothing
*/
static void register_contact_transport_shutdown_cb(void *data)
{
struct contact_transport_monitor *monitor = data;
/*
* Push off to a default serializer. This is in case sorcery
* does database accesses for contacts. Database accesses may
* not be on this machine. We don't want to tie up the pjsip
* monitor thread with potentially long access times.
*/
ao2_ref(monitor, +1);
if (ast_sip_push_task(NULL, register_contact_transport_remove_cb, monitor)) {
ao2_ref(monitor, -1);
}
} }
AST_VECTOR(excess_contact_vector, struct ast_sip_contact *); AST_VECTOR(excess_contact_vector, struct ast_sip_contact *);

Loading…
Cancel
Save