[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