summaryrefslogtreecommitdiff
path: root/res/res_pjsip_registrar_expire.c
diff options
context:
space:
mode:
authorGeorge Joseph <george.joseph@fairview5.com>2016-04-01 12:30:56 -0600
committerJoshua Colp <jcolp@digium.com>2016-04-11 13:00:27 -0500
commita621dd5e963dfef65656d78d1cd212a17245055d (patch)
treeddb29889af0ddc8fca1b253cd17a4d88d55b3029 /res/res_pjsip_registrar_expire.c
parent44fba00ca469391a113bc219ef8e5dab2aff105c (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.c18
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;
}