From: Jaco Kroon Date: Tue, 10 Dec 2024 19:47:49 +0000 (+0200) Subject: res_odbc: release threads from potential starvation. X-Git-Tag: 21.7.0-rc1~36 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=18206add1c2d9bd9f7799319fe8cf737d92849ed;p=thirdparty%2Fasterisk.git res_odbc: release threads from potential starvation. Whenever a slot is freed up due to a failed connection, wake up a waiter before failing. In the case of a dead connection there could be waiters, for example, let's say two threads tries to acquire objects at the same time, with one in the cached connections, one will acquire the dead connection, and the other will enter into the wait state. The thread with the dead connection will clear up the dead connection, and then attempt a re-acquire (at this point there cannot be cached connections else the other thread would have received that and tried to clean up), as such, at this point we're guaranteed that either there are no waiting threads, or that the maxconnections - connection_cnt threads will attempt to re-acquire connections, and then either succeed, using those connections, or failing, and then signalling to release more waiters. Also fix the pointer log for ODBC handle %p dead which would always reflect NULL. Signed-off-by: Jaco Kroon (cherry picked from commit 89ffbb5de7feed2cefb1427fa4b144b442dc4f2a) --- diff --git a/res/res_odbc.c b/res/res_odbc.c index 00e5b2d94b..783424af66 100644 --- a/res/res_odbc.c +++ b/res/res_odbc.c @@ -945,6 +945,7 @@ struct odbc_obj *_ast_odbc_request_obj2(const char *name, struct ast_flags flags if (odbc_obj_connect(obj) == ODBC_FAIL) { ast_mutex_lock(&class->lock); class->connection_cnt--; + ast_cond_signal(&class->cond); ast_mutex_unlock(&class->lock); ao2_ref(obj->parent, -1); ao2_ref(obj, -1); @@ -971,17 +972,18 @@ struct odbc_obj *_ast_odbc_request_obj2(const char *name, struct ast_flags flags /* If the connection is dead try to grab another functional one from the * pool instead of trying to resurrect this one. */ - ao2_ref(obj, -1); - obj = NULL; - ast_mutex_lock(&class->lock); class->connection_cnt--; + /* this thread will re-acquire, and if that fails will signal, + * thus no need to signal class->cond here */ ast_debug(2, "ODBC handle %p dead - removing from class '%s', new count is %zd\n", obj, name, class->connection_cnt); ast_mutex_unlock(&class->lock); + ao2_ref(obj, -1); + obj = NULL; } else { /* We successfully grabbed a connection from the pool and all is well! */