[Asterisk-code-review] res smdi.c: Fix module ref counting and inverted test. (asterisk[13])

George Joseph asteriskteam at digium.com
Fri Oct 5 10:51:59 CDT 2018


George Joseph has submitted this change and it was merged. ( https://gerrit.asterisk.org/10379 )

Change subject: res_smdi.c: Fix module ref counting and inverted test.
......................................................................

res_smdi.c: Fix module ref counting and inverted test.

I think this module is so screwed up that it doesn't work anymore.  Even
with these attempts to fix things it still won't gracefully shut down.
The module refs will not go to zero to allow unloading the module.

* Fix module ref counting dealing with the SMDI interface object.  There
were several off-nominal paths that unbalanced the module ref count.  Also
the destructor freed the ao2 object itself which is bad.  Made the
smdi_read thread not hold its own ref to the SMDI interface object so when
all refs go away the destructor will stop the listener thread.

* Fixed the smdi_load() return code of 1 concerning the number of
listeners.  The test was inverted.

Change-Id: Ic288db51b58e395d6a2fc3847f77176c16988784
---
M res/res_smdi.c
1 file changed, 18 insertions(+), 12 deletions(-)

Approvals:
  George Joseph: Looks good to me, but someone else must approve; Approved for Submit
  Corey Farrell: Looks good to me, but someone else must approve
  Joshua Colp: Looks good to me, approved



diff --git a/res/res_smdi.c b/res/res_smdi.c
index 8622da4..1232839 100644
--- a/res/res_smdi.c
+++ b/res/res_smdi.c
@@ -226,10 +226,12 @@
 static void smdi_interface_destroy(void *obj)
 {
 	struct ast_smdi_interface *iface = obj;
+	int mod_unref_defer = 0;
 
 	if (iface->thread != AST_PTHREADT_NULL && iface->thread != AST_PTHREADT_STOP) {
 		pthread_cancel(iface->thread);
 		pthread_join(iface->thread, NULL);
+		mod_unref_defer = 1;
 	}
 
 	iface->thread = AST_PTHREADT_STOP;
@@ -246,9 +248,9 @@
 	ast_mutex_destroy(&iface->mwi_q_lock);
 	ast_cond_destroy(&iface->mwi_q_cond);
 
-	free(iface);
-
-	ast_module_unref(ast_module_info->self);
+	if (mod_unref_defer) {
+		ast_module_unref(ast_module_info->self);
+	}
 }
 
 /*!
@@ -611,7 +613,6 @@
 
 			md_msg = ao2_alloc(sizeof(*md_msg), NULL);
 			if (!md_msg) {
-				ao2_ref(iface, -1);
 				return NULL;
 			}
 
@@ -621,7 +622,6 @@
 				if (c == EOF) {
 					ast_log(LOG_ERROR, "Unexpected EOF while reading MD message\n");
 					ao2_ref(md_msg, -1);
-					ao2_ref(iface, -1);
 					return NULL;
 				}
 				md_msg->mesg_desk_num[i] = (char) c;
@@ -638,7 +638,6 @@
 				if (c == EOF) {
 					ast_log(LOG_ERROR, "Unexpected EOF while reading SMDI message\n");
 					ao2_ref(md_msg, -1);
-					ao2_ref(iface, -1);
 					return NULL;
 				}
 				md_msg->mesg_desk_term[i] = (char) c;
@@ -654,7 +653,6 @@
 			if (c == EOF) {
 				ast_log(LOG_ERROR, "Unexpected EOF while reading SMDI message\n");
 				ao2_ref(md_msg, -1);
-				ao2_ref(iface, -1);
 				return NULL;
 			}
 			md_msg->type = (char) c;
@@ -733,7 +731,6 @@
 
 			mwi_msg = ao2_alloc(sizeof(*mwi_msg), NULL);
 			if (!mwi_msg) {
-				ao2_ref(iface, -1);
 				return NULL;
 			}
 
@@ -767,7 +764,6 @@
 				if (c == EOF) {
 					ast_log(LOG_ERROR, "Unexpected EOF while reading MWI message\n");
 					ao2_ref(mwi_msg, -1);
-					ao2_ref(iface, -1);
 					return NULL;
 				}
 				mwi_msg->cause[i] = (char) c;
@@ -788,7 +784,6 @@
 	}
 
 	ast_log(LOG_ERROR, "Error reading from SMDI interface %s, stopping listener thread\n", iface->name);
-	ao2_ref(iface, -1);
 	return NULL;
 }
 
@@ -985,6 +980,11 @@
 		return 0;
 
 	new_ifaces = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, smdi_ifaces_cmp_fn);
+	if (!new_ifaces) {
+		ast_config_destroy(conf);
+		return -1;
+	}
+
 	for (v = ast_variable_browse(conf, "interfaces"); v; v = v->next) {
 		RAII_VAR(struct ast_smdi_interface *, iface, NULL, ao2_cleanup);
 
@@ -1107,7 +1107,13 @@
 			/* set the message expiry time */
 			iface->msg_expiry = msg_expiry;
 
-			/* start the listener thread */
+			/*
+			 * start the listener thread
+			 *
+			 * The listener thread does not actually hold a ref to iface.  When all
+			 * external refs go away, the destructor will stop the listener thread
+			 * before actually destroying the iface object.
+			 */
 			ast_verb(3, "Starting SMDI monitor thread for %s\n", iface->name);
 			if (ast_pthread_create_background(&iface->thread, NULL, smdi_read, iface)) {
 				ast_log(LOG_ERROR, "Error starting SMDI monitor thread for %s\n", iface->name);
@@ -1157,7 +1163,7 @@
 		return -1;
 	}
 
-	if (ao2_container_count(new_ifaces)) {
+	if (!ao2_container_count(new_ifaces)) {
 		res = 1;
 	}
 

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

Gerrit-Project: asterisk
Gerrit-Branch: 13
Gerrit-MessageType: merged
Gerrit-Change-Id: Ic288db51b58e395d6a2fc3847f77176c16988784
Gerrit-Change-Number: 10379
Gerrit-PatchSet: 2
Gerrit-Owner: Richard Mudgett <rmudgett at digium.com>
Gerrit-Reviewer: Corey Farrell <git at cfware.com>
Gerrit-Reviewer: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Jenkins2 (1000185)
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20181005/192172b6/attachment.html>


More information about the asterisk-code-review mailing list