mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-29 15:36:13 +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