mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-11-03 20:38:59 +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)
 | 
			
		||||
{
 | 
			
		||||
	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;
 | 
			
		||||
 
 | 
			
		||||
@@ -243,4 +243,9 @@ int ast_odbc_text2isolation(const char *txt);
 | 
			
		||||
 */
 | 
			
		||||
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 */
 | 
			
		||||
 
 | 
			
		||||
@@ -744,6 +744,22 @@ static int aoro2_class_cb(void *obj, void *arg, int flags)
 | 
			
		||||
	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.
 | 
			
		||||
 *
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user