diff options
author | Richard Mudgett <rmudgett@digium.com> | 2018-03-29 17:07:56 -0500 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2018-03-29 16:22:25 -0600 |
commit | 97cc67b12f1c5a0132e095b3e646c6014af554a0 (patch) | |
tree | c70a43a6ff92521cac48bd8b272b453a674dc9a2 /res/res_pjsip_registrar.c | |
parent | 48ef239a01a7b5cacea822cbc4800f640e2dfad1 (diff) |
res_pjsip: Fix deadlock on reliable transport shutdown.
A deadlock can happen when the PJSIP monitor thread is shutting down a
connection oriented transport (TCP/TLS) used by a subscription at the same
time as another thread tries to send something for that subscription. The
deadlock is between the pjsip monitor thread attempting to get the dialog
lock and another thread sending something for that dialog when it tries to
get the transport manager lock.
* res_pjsip_pubsub.c: Avoid the deadlock by pushing the subscription
removal to the subscription serializer.
* res_pjsip_registrar.c: Pushed off incoming registration contact removals
to a default serializer as a precaution. Removing the contacts involves
sorcery access which in this case will involve database access. Depending
upon the setup, the database may not be on the same machine and could take
awhile. We don't want to hold up the pjsip monitor thread with
potentially long access times.
ASTERISK-27706
Change-Id: I56b647aea565f24dba33e9e5ebeed4cd3f31f8c4
Diffstat (limited to 'res/res_pjsip_registrar.c')
-rw-r--r-- | res/res_pjsip_registrar.c | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/res/res_pjsip_registrar.c b/res/res_pjsip_registrar.c index bdee91fb3..985933e2d 100644 --- a/res/res_pjsip_registrar.c +++ b/res/res_pjsip_registrar.c @@ -337,7 +337,7 @@ static int contact_transport_monitor_matcher(void *a, void *b) && 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 ast_sip_contact *contact; @@ -345,7 +345,8 @@ static void register_contact_transport_shutdown_cb(void *data) aor = ast_sip_location_retrieve_aor(monitor->aor_name); if (!aor) { - return; + ao2_ref(monitor, -1); + return 0; } ao2_lock(aor); @@ -365,6 +366,35 @@ static void register_contact_transport_shutdown_cb(void *data) } ao2_unlock(aor); ao2_ref(aor, -1); + + 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 *); |