From e5798d65313ef5022b110e68fbdc81516a5a03e3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?=
 <grubba@grubba.org>
Date: Sun, 8 Feb 1998 16:28:58 +0100
Subject: [PATCH] Fixed some threading bugs.

Rev: src/modules/Mysql/mysql.c:1.11
Rev: src/modules/Mysql/precompiled_mysql.h:1.5
---
 src/modules/Mysql/mysql.c             | 316 ++++++++++++++++++++------
 src/modules/Mysql/precompiled_mysql.h |   7 +-
 2 files changed, 249 insertions(+), 74 deletions(-)

diff --git a/src/modules/Mysql/mysql.c b/src/modules/Mysql/mysql.c
index ce3e34d43a..a736e38ddd 100644
--- a/src/modules/Mysql/mysql.c
+++ b/src/modules/Mysql/mysql.c
@@ -1,5 +1,5 @@
 /*
- * $Id: mysql.c,v 1.10 1997/11/05 20:06:01 hedda Exp $
+ * $Id: mysql.c,v 1.11 1998/02/08 15:28:58 grubba Exp $
  *
  * SQL database functionality for Pike
  *
@@ -73,10 +73,40 @@ typedef struct dynamic_buffer_s dynamic_buffer;
  * Globals
  */
 
-RCSID("$Id: mysql.c,v 1.10 1997/11/05 20:06:01 hedda Exp $");
+RCSID("$Id: mysql.c,v 1.11 1998/02/08 15:28:58 grubba Exp $");
 
 struct program *mysql_program = NULL;
 
+#ifdef HAVE_MYSQL_PORT
+extern unsigned int mysql_port;
+#ifdef _REENTRANT
+static MUTEX_T stupid_port_lock;
+#define STUPID_PORT_INIT()	mt_init(&stupid_port_lock)
+#define STUPID_PORT_LOCK()	mt_lock(&stupid_port_lock)
+#define STUPID_PORT_UNLOCK()	mt_unlock(&stupid_port_lock)
+#define STUPID_PORT_DESTROY()	mt_destroy(&stupid_port_lock)
+#else /* !_REENTRANT */
+#define STUPID_PORT_INIT()
+#define STUPID_PORT_LOCK()
+#define STUPID_PORT_UNLOCK()
+#define STUPID_PORT_DESTROY()
+#endif /* _REENTRANT */
+#endif /* HAVE_MYSQL_PORT */
+
+#ifdef _REENTRANT
+#define MYSQL_LOCK		(&(PIKE_MYSQL->lock))
+#define INIT_MYSQL_LOCK()	mt_init(MYSQL_LOCK)
+#define DESTROY_MYSQL_LOCK()	mt_destroy(MYSQL_LOCK)
+#define MYSQL_ALLOW()		do { MUTEX_T *__l = MYSQL_LOCK; THREADS_ALLOW(); mt_lock(__l);
+#define MYSQL_DISALLOW()	mt_unlock(__l); THREADS_DISALLOW(); } while(0)
+#else /* !_REENTRANT */
+#define INIT_MYSQL_LOCK()
+#define DESTROY_MYSQL_LOCK()
+#define MYSQL_ALLOW()
+#define MYSQL_DISALLOW()
+#endif /* _REENTRANT */
+
+
 /*
  * Functions
  */
@@ -88,6 +118,7 @@ struct program *mysql_program = NULL;
 static void init_mysql_struct(struct object *o)
 {
   MEMSET(PIKE_MYSQL, 0, sizeof(struct precompiled_mysql));
+  INIT_MYSQL_LOCK();
 }
 
 static void exit_mysql_struct(struct object *o)
@@ -115,7 +146,7 @@ static void exit_mysql_struct(struct object *o)
     PIKE_MYSQL->host = NULL;
   }
 
-  THREADS_ALLOW();
+  MYSQL_ALLOW();
 
   if (last_result) {
     mysql_free_result(last_result);
@@ -124,7 +155,9 @@ static void exit_mysql_struct(struct object *o)
     mysql_close(socket);
   }
 
-  THREADS_DISALLOW();
+  MYSQL_DISALLOW();
+
+  DESTROY_MYSQL_LOCK();
 }
 
 
@@ -136,9 +169,20 @@ static void pike_mysql_reconnect(void)
   char *database = NULL;
   char *user = NULL;
   char *password = NULL;
+  char *portptr = NULL;
+  unsigned int port = 0;
+  unsigned int saved_port = 0;
 
   if (PIKE_MYSQL->host) {
-    host = PIKE_MYSQL->host->str;
+    host = strdup(PIKE_MYSQL->host->str);
+    if (!host) {
+      error("Mysql.mysql(): Out of memory!\n");
+    }
+    if ((portptr = strchr(host, ':')) && (*portptr == ':')) {
+      *portptr = 0;
+      portptr++;
+      port = (unsigned int) atoi(portptr);
+    }
   }
   if (PIKE_MYSQL->database) {
     database = PIKE_MYSQL->database->str;
@@ -153,32 +197,58 @@ static void pike_mysql_reconnect(void)
   socket = PIKE_MYSQL->socket;
   PIKE_MYSQL->socket = NULL;
 
-  THREADS_ALLOW();
+  MYSQL_ALLOW();
+
+#ifdef HAVE_MYSQL_PORT
+  STUPID_PORT_LOCK();
+#endif /* HAVE_MYSQL_PORT */
 
   if (socket) {
     /* Disconnect the old connection */
     mysql_close(socket);
   }
 
+#ifdef HAVE_MYSQL_PORT
+  if (port) {
+    saved_port = mysql_port;
+    mysql_port = port;
+  }
+#endif /* HAVE_MYSQL_PORT */
+
   socket = mysql_connect(mysql, host, user, password);
 
-  THREADS_DISALLOW();
+#ifdef HAVE_MYSQL_PORT
+  mysql_port = saved_port;
+
+  STUPID_PORT_UNLOCK();
+#endif /* HAVE_MYSQL_PORT */
 
+  MYSQL_DISALLOW();
+
+  if (host) {
+    /* No longer needed */
+    free(host);
+  }
+  
   if (!(PIKE_MYSQL->socket = socket)) {
     error("Mysql.mysql(): Couldn't reconnect to SQL-server\n");
   }
   if (database) {
     int tmp;
 
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
     tmp = mysql_select_db(socket, database);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
 
     if (tmp < 0) {
-      mysql_close(PIKE_MYSQL->socket);
       PIKE_MYSQL->socket = NULL;
+      MYSQL_ALLOW();
+
+      mysql_close(socket);
+
+      MYSQL_DISALLOW();
       error("Mysql.mysql(): Couldn't select database \"%s\"\n", database);
     }
   }
@@ -241,33 +311,59 @@ static void f_create(INT32 args)
 /* int affected_rows() */
 static void f_affected_rows(INT32 args)
 {
+  MYSQL *socket;
+  int count;
+
   if (!PIKE_MYSQL->socket) {
     pike_mysql_reconnect();
   }
   pop_n_elems(args);
-  push_int(mysql_affected_rows(PIKE_MYSQL->socket));
+  socket = PIKE_MYSQL->socket;
+
+  MYSQL_ALLOW();
+  count = mysql_affected_rows(socket);
+  MYSQL_DISALLOW();
+
+  push_int(count);
 }
 
 /* int insert_id() */
 static void f_insert_id(INT32 args)
 {
+  MYSQL *socket;
+  int id;
+
   if (!PIKE_MYSQL->socket) {
     pike_mysql_reconnect();
   }
   pop_n_elems(args);
-  push_int(mysql_insert_id(PIKE_MYSQL->socket));
+
+  socket = PIKE_MYSQL->socket;
+
+  MYSQL_ALLOW();
+  id = mysql_insert_id(socket);
+  MYSQL_DISALLOW();
+
+  push_int(id);
 }
 
 /* int|string error() */
 static void f_error(INT32 args)
 {
+  MYSQL *socket;
   char *error_msg;
 
   if (!PIKE_MYSQL->socket) {
     pike_mysql_reconnect();
   }
 
-  error_msg = mysql_error(PIKE_MYSQL->socket);
+  socket = PIKE_MYSQL->socket;
+
+  MYSQL_ALLOW();
+
+  error_msg = mysql_error(socket);
+
+  MYSQL_DISALLOW();
 
   pop_n_elems(args);
 
@@ -295,11 +391,11 @@ static void f_select_db(INT32 args)
   database = sp[-args].u.string->str;
 
   if (socket) {
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
     tmp = mysql_select_db(socket, database);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
   if (!socket || (tmp < 0)) {
     /* The connection might have been closed. */
@@ -307,16 +403,22 @@ static void f_select_db(INT32 args)
 
     socket = PIKE_MYSQL->socket;
 
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
     tmp = mysql_select_db(socket, database);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
 
   if (tmp < 0) {
+    char *err;
+
+    MYSQL_ALLOW();
+    err = mysql_error(socket);
+    MYSQL_DISALLOW();
+
     error("mysql->select_db(): Couldn't select database \"%s\" (%s)\n",
-	  sp[-args].u.string->str, mysql_error(PIKE_MYSQL->socket));
+	  sp[-args].u.string->str, err);
   }
   if (PIKE_MYSQL->database) {
     free_string(PIKE_MYSQL->database);
@@ -347,7 +449,7 @@ static void f_big_query(INT32 args)
   qlen = sp[-args].u.string->len;
 
   if (socket) {
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
 #ifdef HAVE_MYSQL_REAL_QUERY
     tmp = mysql_real_query(socket, query, qlen);
@@ -355,7 +457,7 @@ static void f_big_query(INT32 args)
     tmp = mysql_query(socket, query);
 #endif /* HAVE_MYSQL_REAL_QUERY */
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
   if (!socket || (tmp < 0)) {
     /* The connection might have been closed. */
@@ -363,7 +465,7 @@ static void f_big_query(INT32 args)
 
     socket = PIKE_MYSQL->socket;
 
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
 #ifdef HAVE_MYSQL_REAL_QUERY
     tmp = mysql_real_query(socket, query, qlen);
@@ -371,26 +473,38 @@ static void f_big_query(INT32 args)
     tmp = mysql_query(socket, query);
 #endif /* HAVE_MYSQL_REAL_QUERY */
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
 
   if (tmp < 0) {
+    char *err;
+
+    MYSQL_ALLOW();
+    err = mysql_error(socket);
+    MYSQL_DISALLOW();
+
     error("mysql->big_query(): Query \"%s\" failed (%s)\n",
-	  sp[-args].u.string->str, mysql_error(PIKE_MYSQL->socket));
+	  sp[-args].u.string->str, err);
   }
 
-  THREADS_ALLOW();
+  MYSQL_ALLOW();
 
   /* The same thing applies here */
 
   result = mysql_store_result(socket);
 
-  THREADS_DISALLOW();
+  MYSQL_DISALLOW();
 
   pop_n_elems(args);
 
   if (!(PIKE_MYSQL->last_result = result)) {
-    if (mysql_num_fields(socket) && mysql_error(socket)[0]) {
+    int err;
+
+    MYSQL_ALLOW();
+    err = (mysql_num_fields(socket) && mysql_error(socket)[0]);
+    MYSQL_DISALLOW();
+
+    if (err) {
       error("mysql->big_query(): Couldn't create result for query\n");
     }
     /* query was INSERT or similar - return 0 */
@@ -426,11 +540,11 @@ static void f_create_db(INT32 args)
   database = sp[-args].u.string->str;
 
   if (socket) {
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
     tmp = mysql_create_db(socket, database);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
   if (!socket || (tmp < 0)) {
     /* The connection might have been closed */
@@ -438,11 +552,11 @@ static void f_create_db(INT32 args)
 
     socket = PIKE_MYSQL->socket;
 
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
     tmp = mysql_create_db(socket, database);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
 
   if (tmp < 0) {
@@ -473,11 +587,11 @@ static void f_drop_db(INT32 args)
   database = sp[-args].u.string->str;
 
   if (socket) {
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
     tmp = mysql_drop_db(socket, database);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
   if (!socket || (tmp < 0)) {
     /* The connection might have been closed */
@@ -485,11 +599,11 @@ static void f_drop_db(INT32 args)
 
     socket = PIKE_MYSQL->socket;
 
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
     tmp = mysql_drop_db(socket, database);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }    
 
   if (tmp < 0) {
@@ -507,11 +621,11 @@ static void f_shutdown(INT32 args)
   int tmp = -1;
 
   if (socket) {
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
   
     tmp = mysql_shutdown(socket);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
   if (!socket || (tmp < 0)) {
     /* The connection might have been closed */
@@ -519,11 +633,11 @@ static void f_shutdown(INT32 args)
 
     socket = PIKE_MYSQL->socket;
 
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
   
     tmp = mysql_shutdown(socket);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
 
   if (tmp < 0) {
@@ -540,11 +654,11 @@ static void f_reload(INT32 args)
   int tmp = -1;
 
   if (socket) {
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
     tmp = mysql_reload(socket);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
   if (!socket || (tmp < 0)) {
     /* The connection might have been closed */
@@ -552,11 +666,11 @@ static void f_reload(INT32 args)
 
     socket = PIKE_MYSQL->socket;
 
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
     tmp = mysql_reload(socket);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
 
   if (tmp < 0) {
@@ -579,11 +693,11 @@ static void f_statistics(INT32 args)
 
   pop_n_elems(args);
 
-  THREADS_ALLOW();
+  MYSQL_ALLOW();
 
   stats = mysql_stat(socket);
 
-  THREADS_DISALLOW();
+  MYSQL_DISALLOW();
 
   push_text(stats);
 }
@@ -603,11 +717,11 @@ static void f_server_info(INT32 args)
 
   push_text("mysql/");
 
-  THREADS_ALLOW();
+  MYSQL_ALLOW();
 
   info = mysql_get_server_info(socket);
 
-  THREADS_DISALLOW();
+  MYSQL_DISALLOW();
 
   push_text(info);
   f_add(2);
@@ -616,25 +730,45 @@ static void f_server_info(INT32 args)
 /* string host_info() */
 static void f_host_info(INT32 args)
 {
+  MYSQL *socket;
+  char *info;
+
   if (!PIKE_MYSQL->socket) {
     pike_mysql_reconnect();
   }
 
+  socket = PIKE_MYSQL->socket;
+
   pop_n_elems(args);
 
-  push_text(mysql_get_host_info(PIKE_MYSQL->socket));
+  MYSQL_ALLOW();
+
+  info = mysql_get_host_info(socket);
+
+  MYSQL_DISALLOW();
+
+  push_text(info);
 }
 
 /* int protocol_info() */
 static void f_protocol_info(INT32 args)
 {
+  MYSQL *socket;
+  int prot;
+
   if (!PIKE_MYSQL->socket) {
     pike_mysql_reconnect();
   }
 
   pop_n_elems(args);
 
-  push_int(mysql_get_proto_info(PIKE_MYSQL->socket));
+  socket = PIKE_MYSQL->socket;
+
+  MYSQL_ALLOW();
+  prot = mysql_get_proto_info(socket);
+  MYSQL_DISALLOW();
+
+  push_int(prot);
 }
 
 /* object(mysql_res) list_dbs(void|string wild) */
@@ -656,11 +790,11 @@ static void f_list_dbs(INT32 args)
   }
 
   if (socket) {
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
     result = mysql_list_dbs(socket, wild);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
   if (!socket || !result) {
     /* The connection might have been closed */
@@ -668,16 +802,23 @@ static void f_list_dbs(INT32 args)
 
     socket = PIKE_MYSQL->socket;
 
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
     result = mysql_list_dbs(socket, wild);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
 
   if (!(PIKE_MYSQL->last_result = result)) {
-    error("mysql->list_dbs(): Cannot list databases: %s\n",
-	  mysql_error(socket));
+    char *err;
+
+    MYSQL_ALLOW();
+
+    err = mysql_error(socket);
+
+    MYSQL_DISALLOW();
+
+    error("mysql->list_dbs(): Cannot list databases: %s\n", err);
   }
 
   pop_n_elems(args);
@@ -707,11 +848,11 @@ static void f_list_tables(INT32 args)
   }
 
   if (socket) {
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
     result = mysql_list_tables(socket, wild);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
   if (!socket || !result) {
     /* The connection might have been closed */
@@ -719,16 +860,23 @@ static void f_list_tables(INT32 args)
 
     socket = PIKE_MYSQL->socket;
 
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
     result = mysql_list_tables(socket, wild);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
 
   if (!(PIKE_MYSQL->last_result = result)) {
-    error("mysql->list_tables(): Cannot list databases: %s\n",
-	  mysql_error(PIKE_MYSQL->socket));
+    char *err;
+
+    MYSQL_ALLOW();
+
+    err =  mysql_error(socket);
+
+    MYSQL_DISALLOW();
+
+    error("mysql->list_tables(): Cannot list databases: %s\n", err);
   }
 
   pop_n_elems(args);
@@ -774,11 +922,11 @@ static void f_list_fields(INT32 args)
   }
 
   if (socket) {
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
     result = mysql_list_fields(socket, table, wild);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
   if (!socket || !result) {
     /* The connection might have been closed */
@@ -786,20 +934,29 @@ static void f_list_fields(INT32 args)
 
     socket = PIKE_MYSQL->socket;
 
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
     result = mysql_list_fields(socket, table, wild);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
 
   if (!result) {
-    error("mysql->list_fields(): Cannot list databases: %s\n",
-	  mysql_error(PIKE_MYSQL->socket));
+    char *err;
+
+    MYSQL_ALLOW();
+
+    err = mysql_error(socket);
+
+    MYSQL_DISALLOW();
+
+    error("mysql->list_fields(): Cannot list databases: %s\n", err);
   }
 
   pop_n_elems(args);
 
+  /* FIXME: Should have MYSQL_{DIS,}ALLOW() here */
+
   while ((field = mysql_fetch_field(result))) {
     mysqlmod_parse_field(field, 1);
     i++;
@@ -816,11 +973,11 @@ static void f_list_processes(INT32 args)
   pop_n_elems(args);
 
   if (socket) {
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
     result = mysql_list_processes(socket);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
   if (!socket || !result) {
     /* The connection might have been closed */
@@ -828,16 +985,23 @@ static void f_list_processes(INT32 args)
 
     socket = PIKE_MYSQL->socket;
 
-    THREADS_ALLOW();
+    MYSQL_ALLOW();
 
     result = mysql_list_processes(socket);
 
-    THREADS_DISALLOW();
+    MYSQL_DISALLOW();
   }
 
   if (!(PIKE_MYSQL->last_result = result)) {
-    error("mysql->list_processes(): Cannot list databases: %s\n",
-	  mysql_error(PIKE_MYSQL->socket));
+    char *err;
+
+    MYSQL_ALLOW();
+
+    err = mysql_error(socket);
+
+    MYSQL_DISALLOW();
+
+    error("mysql->list_processes(): Cannot list databases: %s\n", err);
   }
 
   push_object(fp->current_object);
@@ -916,6 +1080,10 @@ void pike_module_init(void)
   mysql_program = end_program();
   add_program_constant("mysql", mysql_program, 0);
 
+#ifdef HAVE_MYSQL_PORT
+  STUPID_PORT_INIT();
+#endif /* HAVE_MYSQL_PORT */
+
   init_mysql_res_programs();
 #endif /* HAVE_MYSQL */
 }
@@ -925,6 +1093,10 @@ void pike_module_exit(void)
 #ifdef HAVE_MYSQL
   exit_mysql_res();
 
+#ifdef HAVE_MYSQL_PORT
+  STUPID_PORT_DESTROY();
+#endif /* HAVE_MYSQL_PORT */
+
   if (mysql_program) {
     free_program(mysql_program);
     mysql_program = NULL;
diff --git a/src/modules/Mysql/precompiled_mysql.h b/src/modules/Mysql/precompiled_mysql.h
index a6c9e0bca6..571d4016db 100644
--- a/src/modules/Mysql/precompiled_mysql.h
+++ b/src/modules/Mysql/precompiled_mysql.h
@@ -1,5 +1,5 @@
 /*
- * $Id: precompiled_mysql.h,v 1.4 1997/06/30 20:00:07 grubba Exp $
+ * $Id: precompiled_mysql.h,v 1.5 1998/02/08 15:28:58 grubba Exp $
  *
  * SQL database connectivity for Pike
  *
@@ -18,7 +18,7 @@
 #endif /* HAVE_CONFIG_H */
 
 /* From the mysql-dist */
-/* Workaround for versions prior to 3.20.0 not beeing protected for
+/* Workaround for versions prior to 3.20.0 not beeing protected against
  * multiple inclusion.
  */
 #ifndef _mysql_h
@@ -43,6 +43,9 @@
  */
 
 struct precompiled_mysql {
+#ifdef MUTEX_T
+  MUTEX_T	lock;
+#endif /* MUTEX_T */
   MYSQL		mysql, *socket;
   MYSQL_RES	*last_result;	/* UGLY way to pass arguments to create() */
   struct pike_string	*host, *database, *user, *password;	/* Reconnect */
-- 
GitLab