[Asterisk-code-review] astobj2: Assert on attempt to lock object with no locking. (asterisk[master])

Corey Farrell asteriskteam at digium.com
Tue Oct 2 13:42:47 CDT 2018


Corey Farrell has uploaded this change for review. ( https://gerrit.asterisk.org/10376


Change subject: astobj2: Assert on attempt to lock object with no locking.
......................................................................

astobj2: Assert on attempt to lock object with no locking.

Add assertion when __ao2_lock or __ao2_trylock are called against an
object that does not contain a lock.  No assertion is performed by
__adjust_lock as this is used by functions which use the OBJ_NOLOCK
flag.  Inject OBJ_NOLOCK for standard ao2_container operations if the
container was allocated without locking.

Remove invalid locking of PJSIP CLI formatter registry.

Change-Id: I5518e55739769792a76f766ce25880d7d944f63b
---
M main/astobj2.c
M main/astobj2_container.c
M main/astobj2_private.h
M res/res_pjsip/pjsip_cli.c
4 files changed, 32 insertions(+), 4 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/76/10376/1

diff --git a/main/astobj2.c b/main/astobj2.c
index 23109a6..13f4648 100644
--- a/main/astobj2.c
+++ b/main/astobj2.c
@@ -178,6 +178,16 @@
 	return !p || IS_AO2_MAGIC_BAD(p) ? 0 : 1;
 }
 
+int internal_ao2_nolock(void *user_data)
+{
+	struct astobj2 *p = INTERNAL_OBJ(user_data);
+
+	ast_assert(p != NULL);
+
+	return (p->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) == AO2_ALLOC_OPT_LOCK_NOLOCK
+		? OBJ_NOLOCK : 0;
+}
+
 void log_bad_ao2(void *user_data, const char *file, int line, const char *func)
 {
 	struct astobj2 *p;
@@ -242,7 +252,8 @@
 		break;
 	case AO2_ALLOC_OPT_LOCK_NOLOCK:
 		/* The ao2 object has no lock. */
-		break;
+		__ast_assert_failed(0, "ao2_lock called on object with no locking.", file, line, func);
+		return -1;
 	case AO2_ALLOC_OPT_LOCK_OBJ:
 		obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
 		res = __ao2_lock(obj_lockobj->lockobj.lock, lock_how, file, func, line, var);
@@ -358,7 +369,8 @@
 		break;
 	case AO2_ALLOC_OPT_LOCK_NOLOCK:
 		/* The ao2 object has no lock. */
-		return 0;
+		__ast_assert_failed(0, "ao2_trylock called on object with no locking.", file, line, func);
+		return -1;
 	case AO2_ALLOC_OPT_LOCK_OBJ:
 		obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
 		res = __ao2_trylock(obj_lockobj->lockobj.lock, lock_how, file, func, line, var);
@@ -433,6 +445,8 @@
 		ast_log(LOG_ERROR, "Invalid lock option on ao2 object %p\n", user_data);
 		/* Fall through */
 	case AO2_ALLOC_OPT_LOCK_NOLOCK:
+		/* No assertion for __adjust_lock, this is used internally by AO2 code
+		 * that uses OBJ_NOLOCK. */
 	case AO2_ALLOC_OPT_LOCK_MUTEX:
 		orig_lock = AO2_LOCK_REQ_MUTEX;
 		break;
diff --git a/main/astobj2_container.c b/main/astobj2_container.c
index 9bea58f..88810dc 100644
--- a/main/astobj2_container.c
+++ b/main/astobj2_container.c
@@ -109,6 +109,7 @@
 		return 0;
 	}
 
+	flags |= internal_ao2_nolock(self);
 	if (flags & OBJ_NOLOCK) {
 		orig_lock = __adjust_lock(self, AO2_LOCK_REQ_WRLOCK, 1);
 	} else {
@@ -296,6 +297,7 @@
 	}
 
 	/* avoid modifications to the content */
+	flags |= internal_ao2_nolock(self);
 	if (flags & OBJ_NOLOCK) {
 		if (flags & OBJ_UNLINK) {
 			orig_lock = __adjust_lock(self, AO2_LOCK_REQ_WRLOCK, 1);
@@ -489,6 +491,10 @@
 		.flags = flags
 	};
 
+	if (internal_ao2_nolock(c)) {
+		a.flags |= AO2_ITERATOR_DONTLOCK;
+	}
+
 	ao2_t_ref(c, +1, "Init iterator with container.");
 
 	return a;
diff --git a/main/astobj2_private.h b/main/astobj2_private.h
index ef47ed7..9975112 100644
--- a/main/astobj2_private.h
+++ b/main/astobj2_private.h
@@ -61,6 +61,16 @@
 #define is_ao2_object(user_data) \
 	__is_ao2_object(user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
+/*!
+ * \brief Determine if locking should be skipped.
+ *
+ * \retval OBJ_NOLOCK if the object was allocated with AO2_ALLOC_OPT_LOCK_NOLOCK.
+ * \retval 0 if the object has a lock.
+ *
+ * \note This function is not NULL safe and assumes \a user_data points to a valid object.
+ * */
+int internal_ao2_nolock(void *user_data);
+
 enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger);
 
 #endif /* ASTOBJ2_PRIVATE_H_ */
diff --git a/res/res_pjsip/pjsip_cli.c b/res/res_pjsip/pjsip_cli.c
index 4544a17..52b1f76 100644
--- a/res/res_pjsip/pjsip_cli.c
+++ b/res/res_pjsip/pjsip_cli.c
@@ -326,11 +326,9 @@
 int ast_sip_unregister_cli_formatter(struct ast_sip_cli_formatter_entry *formatter)
 {
 	if (formatter) {
-		ao2_wrlock(formatter_registry);
 		if (ao2_ref(formatter, -1) == 2) {
 			ao2_unlink_flags(formatter_registry, formatter, OBJ_NOLOCK);
 		}
-		ao2_unlock(formatter_registry);
 	}
 	return 0;
 }

-- 
To view, visit https://gerrit.asterisk.org/10376
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I5518e55739769792a76f766ce25880d7d944f63b
Gerrit-Change-Number: 10376
Gerrit-PatchSet: 1
Gerrit-Owner: Corey Farrell <git at cfware.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20181002/6015a935/attachment-0001.html>


More information about the asterisk-code-review mailing list