[Asterisk-code-review] func odbc: Fix connection deadlock. (asterisk[master])

Joshua Colp asteriskteam at digium.com
Tue Jul 12 05:00:16 CDT 2016


Joshua Colp has uploaded a new change for review.

  https://gerrit.asterisk.org/3174

Change subject: func_odbc: Fix connection deadlock.
......................................................................

func_odbc: Fix connection deadlock.

The func_odbc module was modified to ensure that the
previous behavior of using a single database connection
was maintained. This was done by getting a single database
connection and holding on to it. With the new multiple
connection support in res_odbc this will actually starve
every other thread from getting access to the database as
it also maintains the previous behavior of having only
a single database connection.

This change disables the func_odbc specific behavior if
the res_odbc module is running with only a single database
connection active. The connection is only kept for the
duration of the request.

ASTERISK-26177 #close

Change-Id: I9bdbd8a300fb3233877735ad3fd07bce38115b7f
---
M funcs/func_odbc.c
M include/asterisk/res_odbc.h
M res/res_odbc.c
3 files changed, 37 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/74/3174/1

diff --git a/funcs/func_odbc.c b/funcs/func_odbc.c
index 489f373..224cd7a 100644
--- a/funcs/func_odbc.c
+++ b/funcs/func_odbc.c
@@ -388,9 +388,25 @@
 static inline void release_obj_or_dsn(struct odbc_obj **obj, struct dsn **dsn)
 {
 	if (dsn && *dsn) {
+		/* If multiple connections are not enabled then the guarantee
+		 * of a single connection already exists and holding on to the
+		 * connection would prevent any other user from acquiring it
+		 * indefinitely.
+		 */
+		if (ast_odbc_get_max_connections((*dsn)->name) < 2) {
+			ast_odbc_release_obj((*dsn)->connection);
+			(*dsn)->connection = NULL;
+		}
 		ao2_unlock(*dsn);
 		ao2_ref(*dsn, -1);
 		*dsn = NULL;
+		/* Some callers may provide both an obj and dsn. To ensure that
+		 * the connection is not released twice we set it to NULL here if
+		 * present.
+		 */
+		if (obj) {
+			*obj = NULL;
+		}
 	} else if (obj && *obj) {
 		ast_odbc_release_obj(*obj);
 		*obj = NULL;
diff --git a/include/asterisk/res_odbc.h b/include/asterisk/res_odbc.h
index 8c7b549..137f7d4 100644
--- a/include/asterisk/res_odbc.h
+++ b/include/asterisk/res_odbc.h
@@ -243,4 +243,9 @@
  */
 const char *ast_odbc_isolation2text(int iso);
 
+/*!
+ * \brief Return the current configured maximum number of connections for a class
+ */
+unsigned int ast_odbc_get_max_connections(const char *name);
+
 #endif /* _ASTERISK_RES_ODBC_H */
diff --git a/res/res_odbc.c b/res/res_odbc.c
index a89c954..bd64b9f 100644
--- a/res/res_odbc.c
+++ b/res/res_odbc.c
@@ -744,6 +744,22 @@
 	return 0;
 }
 
+unsigned int ast_odbc_get_max_connections(const char *name)
+{
+	struct odbc_class *class;
+	unsigned int max_connections;
+
+	class = ao2_callback(class_container, 0, aoro2_class_cb, (char *) name);
+	if (!class) {
+		return 0;
+	}
+
+	max_connections = class->maxconnections;
+	ao2_ref(class, -1);
+
+	return max_connections;
+}
+
 /*
  * \brief Determine if the connection has died.
  *

-- 
To view, visit https://gerrit.asterisk.org/3174
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I9bdbd8a300fb3233877735ad3fd07bce38115b7f
Gerrit-PatchSet: 1
Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Owner: Joshua Colp <jcolp at digium.com>



More information about the asterisk-code-review mailing list