diff options
author | George Joseph <george.joseph@fairview5.com> | 2016-04-01 12:30:56 -0600 |
---|---|---|
committer | Joshua Colp <jcolp@digium.com> | 2016-04-11 13:00:27 -0500 |
commit | a621dd5e963dfef65656d78d1cd212a17245055d (patch) | |
tree | ddb29889af0ddc8fca1b253cd17a4d88d55b3029 /res/res_pjsip_registrar_expire.c | |
parent | 44fba00ca469391a113bc219ef8e5dab2aff105c (diff) |
res_pjsip contact: Lock expiration/addition of contacts
Contact expiration can occur in several places: res_pjsip_registrar,
res_pjsip_registrar_expire, and automatically when anyone calls
ast_sip_location_retrieve_aor_contact. At the same time, res_pjsip_registrar
may also be attempting to renew or add a contact. Since none of this was locked
it was possible for one thread to be renewing a contact and another thread to
expire it immediately because it was working off of stale data. This was the
casue of intermittent registration/inbound/nominal/multiple_contacts test
failures.
Now, the new named lock functionality is used to lock the aor during contact
expire and add operations and res_pjsip_registrar_expire now checks the
expiration with the lock held before deleting the contact.
ASTERISK-25885 #close
Reported-by: Josh Colp
Change-Id: I83d413c46a47796f3ab052ca3b349f21cca47059
Diffstat (limited to 'res/res_pjsip_registrar_expire.c')
-rw-r--r-- | res/res_pjsip_registrar_expire.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/res/res_pjsip_registrar_expire.c b/res/res_pjsip_registrar_expire.c index e52363e13..0d979a13f 100644 --- a/res/res_pjsip_registrar_expire.c +++ b/res/res_pjsip_registrar_expire.c @@ -30,6 +30,7 @@ #include "asterisk/res_pjsip.h" #include "asterisk/module.h" +#include "asterisk/named_locks.h" /*! \brief Thread keeping things alive */ static pthread_t check_thread = AST_PTHREADT_NULL; @@ -41,8 +42,23 @@ static unsigned int check_interval; static int expire_contact(void *obj, void *arg, int flags) { struct ast_sip_contact *contact = obj; + struct ast_named_lock *lock; - ast_sorcery_delete(ast_sip_get_sorcery(), contact); + lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_RWLOCK, "aor", contact->aor); + if (!lock) { + return 0; + } + + /* + * We need to check the expiration again with the aor lock held + * in case another thread is attempting to renew the contact. + */ + ao2_wrlock(lock); + if (ast_tvdiff_ms(ast_tvnow(), contact->expiration_time) > 0) { + ast_sip_location_delete_contact(contact); + } + ao2_unlock(lock); + ast_named_lock_put(lock); return 0; } |