mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-06 04:30:28 +00:00
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
This commit is contained in:
@@ -388,9 +388,25 @@ static struct odbc_obj *get_odbc_obj(const char *dsn_name, struct dsn **dsn)
|
|||||||
static inline void release_obj_or_dsn(struct odbc_obj **obj, struct dsn **dsn)
|
static inline void release_obj_or_dsn(struct odbc_obj **obj, struct dsn **dsn)
|
||||||
{
|
{
|
||||||
if (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_unlock(*dsn);
|
||||||
ao2_ref(*dsn, -1);
|
ao2_ref(*dsn, -1);
|
||||||
*dsn = NULL;
|
*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) {
|
} else if (obj && *obj) {
|
||||||
ast_odbc_release_obj(*obj);
|
ast_odbc_release_obj(*obj);
|
||||||
*obj = NULL;
|
*obj = NULL;
|
||||||
|
@@ -243,4 +243,9 @@ int ast_odbc_text2isolation(const char *txt);
|
|||||||
*/
|
*/
|
||||||
const char *ast_odbc_isolation2text(int iso);
|
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 */
|
#endif /* _ASTERISK_RES_ODBC_H */
|
||||||
|
@@ -744,6 +744,22 @@ static int aoro2_class_cb(void *obj, void *arg, int flags)
|
|||||||
return 0;
|
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.
|
* \brief Determine if the connection has died.
|
||||||
*
|
*
|
||||||
|
Reference in New Issue
Block a user