From 843950e7a85730b796bb6238b6e91111f7209c25 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sat, 7 Jul 2007 19:11:45 +0200 Subject: [PATCH] mysql_selector.c: introduce the myslq lock This fixes a race condition in para_server: parent child real_query real_query mysql_store_result This could cause para_server to hang in case the child process issued a query which does not yield a result. It's hard to hit though. Fix is to take the lock before the call to real_query, and release it after mysql_store_result(). The patch also fixes a format string bug which was introduced by the patch that switched to my_ulonglong for suitable variables in mysql_selector.c. These need "%lli". --- mysql_selector.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/mysql_selector.c b/mysql_selector.c index 8148fabe..dedc96cc 100644 --- a/mysql_selector.c +++ b/mysql_selector.c @@ -22,11 +22,13 @@ #include "string.h" #include "user_list.h" #include "mysql_selector_command_list.h" +#include "ipc.h" /** pointer to the shared memory area */ extern struct misc_meta_data *mmd; static void *mysql_ptr = NULL; +static int mysql_lock; /** * contains name/replacement pairs used by s_a_r_list() @@ -152,7 +154,7 @@ __must_check __malloc static char *s_a_r_list(const struct para_macro *macro_lis return ret; } -static int real_query(const char *query) +static int lockless_real_query(const char *query) { if (!mysql_ptr) return -E_NOTCONN; @@ -165,19 +167,32 @@ static int real_query(const char *query) return 1; } +static int real_query(const char *query) +{ + int ret; + + mutex_lock(mysql_lock); + ret = lockless_real_query(query); + mutex_unlock(mysql_lock); + return ret; +} + /* * Use open connection given by mysql_ptr to query server. Returns a * result pointer on succes and NULL on errors */ static struct MYSQL_RES *get_result(const char *query) { - void *result; + void *result = NULL; - if (real_query(query) < 0) - return NULL; + mutex_lock(mysql_lock); + if (lockless_real_query(query) < 0) + goto out; result = mysql_store_result(mysql_ptr); if (!result) PARA_ERROR_LOG("%s", "store_result error\n"); +out: + mutex_unlock(mysql_lock); return result; } /* @@ -1947,7 +1962,7 @@ static int com_vrfy_clean(int fd, int argc, __a_unused char *argv[]) goto out; } if (vrfy_mode) { - send_va_buffer(fd, "found %i invalid entr%s\n", num_rows, + send_va_buffer(fd, "found %lli invalid entr%s\n", num_rows, num_rows == 1? "y" : "ies"); ret = print_results(fd, result, top, left, num_rows - 1, right); goto out; @@ -2244,11 +2259,18 @@ out: static void shutdown_connection(void) { + int ret; + if (mysql_ptr) { PARA_NOTICE_LOG("%s", "shutting down mysql connection\n"); mysql_close(mysql_ptr); mysql_ptr = NULL; } + if (mysql_lock) { + ret = mutex_destroy(mysql_lock); + if (ret < 0) + PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret)); + } } /** @@ -2280,6 +2302,10 @@ int mysql_selector_init(struct audio_file_selector *db) db->get_audio_file_list = server_get_audio_file_list; db->update_audio_file = update_audio_file_server_handler; db->shutdown = shutdown_connection; + ret = mutex_new(); + if (ret < 0) + return ret; + mysql_lock = ret; ret = init_mysql_server(); if (ret < 0) PARA_WARNING_LOG("%s\n", PARA_STRERROR(-ret)); -- 2.39.2