List:Commits« Previous MessageNext Message »
From:holyfoot Date:June 1 2006 12:06pm
Subject:bk commit into 4.1 tree (holyfoot:1.2490) BUG#16017
View as plain text  
Below is the list of changes that have just been committed into a local
4.1 repository of hf. When hf does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.2490 06/06/01 17:06:42 holyfoot@deer.(none) +8 -0
  bug #16017 (memory leaks in embedded server)
  
  There actually was 3 different problems -
  hash_user_connections wasn't cleaned
  one strdupped database name wasn't freed
  and stmt->mem_root wasn't cleaned as it was
  replased with mysql->field_alloc for result
  For the last one - i made the library using stmt's
  fields to store result if it's the case.

  sql/sql_parse.cc
    1.481 06/06/01 17:05:55 holyfoot@stripped +12 -6
    hash_user_connections isn't used if no access checks compiled

  sql-common/client.c
    1.89 06/06/01 17:05:55 holyfoot@stripped +2 -1
    stmt fake attribute added to cli_advanced_command

  libmysqld/libmysqld.c
    1.66 06/06/01 17:05:55 holyfoot@stripped +3 -6
    it's enough to only send database pointer to check_embedded_connection

  libmysqld/lib_sql.cc
    1.126 06/06/01 17:05:55 holyfoot@stripped +31 -22
    Now we store result directly in the MYSQL_STMT structure to
    avoid extra copying

  libmysqld/embedded_priv.h
    1.13 06/06/01 17:05:55 holyfoot@stripped +3 -3
    it's enough to send database name to check_embedded_connection

  libmysql/libmysql.c
    1.303 06/06/01 17:05:55 holyfoot@stripped +7 -6
    stmt pointer now sent to advanced_command

  include/sql_common.h
    1.15 06/06/01 17:05:55 holyfoot@stripped +2 -1
    stmt added to the cli_advanced_command interface

  include/mysql.h
    1.143 06/06/01 17:05:55 holyfoot@stripped +14 -3
    statement pointer added to the advanced_command to be checked in
    embedded server

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	holyfoot
# Host:	deer.(none)
# Root:	/home/hf/work/mysql-4.1.16017

--- 1.142/include/mysql.h	Tue Jul 19 20:11:55 2005
+++ 1.143/include/mysql.h	Thu Jun  1 17:05:55 2006
@@ -216,6 +216,7 @@
 };
 
 struct st_mysql_methods;
+struct st_mysql_stmt;
 
 typedef struct st_mysql
 {
@@ -269,6 +270,12 @@
     from mysql_stmt_close if close had to cancel result set of this object.
   */
   my_bool *unbuffered_fetch_owner;
+  /*
+    In embedded server it points to the statement that is processed
+    in the current query. We store some results directly in statement
+    fields then.
+  */
+  struct st_mysql_stmt *current_stmt;
 } MYSQL;
 
 typedef struct st_mysql_res {
@@ -636,7 +643,8 @@
 			      unsigned long header_length,
 			      const char *arg,
 			      unsigned long arg_length,
-			      my_bool skip_check);
+			      my_bool skip_check,
+                              MYSQL_STMT *stmt);
   MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
 			   unsigned int fields);
   MYSQL_RES * (*use_result)(MYSQL *mysql);
@@ -724,8 +732,11 @@
 */
 
 #define simple_command(mysql, command, arg, length, skip_check) \
-  (*(mysql)->methods->advanced_command)(mysql, command,         \
-					NullS, 0, arg, length, skip_check)
+  (*(mysql)->methods->advanced_command)(mysql, command, NullS,  \
+                                        0, arg, length, skip_check, NULL)
+#define stmt_command(mysql, command, arg, length, stmt) \
+  (*(mysql)->methods->advanced_command)(mysql, command, NullS,  \
+                                        0, arg, length, 1, stmt)
 unsigned long net_safe_read(MYSQL* mysql);
 
 #ifdef __NETWARE__

--- 1.302/libmysql/libmysql.c	Thu Apr  6 11:46:21 2006
+++ 1.303/libmysql/libmysql.c	Thu Jun  1 17:05:55 2006
@@ -2085,7 +2085,7 @@
       mysql_use_result it won't be freed in mysql_stmt_free_result and
       we should get 'Commands out of sync' here.
     */
-    if (simple_command(mysql, COM_CLOSE_STMT, buff, 4, 1))
+    if (stmt_command(mysql, COM_CLOSE_STMT, buff, 4, stmt))
     {
       set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
                       mysql->net.sqlstate);
@@ -2094,7 +2094,7 @@
     stmt->state= MYSQL_STMT_INIT_DONE;
   }
 
-  if (simple_command(mysql, COM_PREPARE, query, length, 1))
+  if (stmt_command(mysql, COM_PREPARE, query, length, stmt))
   {
     set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
                     mysql->net.sqlstate);
@@ -2505,7 +2505,7 @@
   buff[4]= (char) 0;                            /* no flags */
   int4store(buff+5, 1);                         /* iteration count */
   if (cli_advanced_command(mysql, COM_EXECUTE, buff, sizeof(buff),
-                           packet, length, 1) ||
+                           packet, length, 1, NULL) ||
       (*mysql->methods->read_query_result)(mysql))
   {
     set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
@@ -3279,7 +3279,8 @@
       This is intentional to save bandwidth.
     */
     if ((*mysql->methods->advanced_command)(mysql, COM_LONG_DATA, buff,
-					    sizeof(buff), data, length, 1))
+					    sizeof(buff), data, length, 1,
+                                            NULL))
     {
       set_stmt_errmsg(stmt, mysql->net.last_error,
 		      mysql->net.last_errno, mysql->net.sqlstate);
@@ -4603,7 +4604,7 @@
         mysql->status= MYSQL_STATUS_READY;
       }
       int4store(buff, stmt->stmt_id);
-      if ((rc= simple_command(mysql, COM_CLOSE_STMT, buff, 4, 1)))
+      if ((rc= stmt_command(mysql, COM_CLOSE_STMT, buff, 4, stmt)))
       {
         set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
                         mysql->net.sqlstate);
@@ -4641,7 +4642,7 @@
   mysql= stmt->mysql->last_used_con;
   int4store(buff, stmt->stmt_id);		/* Send stmt id to server */
   if ((*mysql->methods->advanced_command)(mysql, COM_RESET_STMT, buff,
-                                          sizeof(buff), 0, 0, 0))
+                                          sizeof(buff), 0, 0, 0, 0))
   {
     set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
                     mysql->net.sqlstate);

--- 1.480/sql/sql_parse.cc	Wed Apr 26 22:10:15 2006
+++ 1.481/sql/sql_parse.cc	Thu Jun  1 17:05:55 2006
@@ -54,8 +54,8 @@
 static void time_out_user_resource_limits(THD *thd, USER_CONN *uc);
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
 static int check_for_max_user_connections(THD *thd, USER_CONN *uc);
-#endif
 static void decrease_user_connections(USER_CONN *uc);
+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
 static bool check_db_used(THD *thd,TABLE_LIST *tables);
 static bool check_multi_update_lock(THD *thd, TABLE_LIST *tables, 
 				    List<Item> *fields, SELECT_LEX *select_lex);
@@ -137,6 +137,7 @@
 #endif
 
 
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
 static HASH hash_user_connections;
 
 static int get_or_create_user_conn(THD *thd, const char *user,
@@ -190,6 +191,7 @@
   return return_val;
 
 }
+#endif /* !NO_EMBEDDED_ACCESS_CHECKS */
 
 
 /*
@@ -231,11 +233,7 @@
     thd->db= 0;
     thd->db_length= 0;
     if (mysql_change_db(thd, db))
-    {
-      if (thd->user_connect)
-	decrease_user_connections(thd->user_connect);
       DBUG_RETURN(-1);
-    }
   }
   else
     send_ok(thd);
@@ -409,10 +407,12 @@
 
 void init_max_user_conn(void)
 {
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
   (void) hash_init(&hash_user_connections,system_charset_info,max_connections,
 		   0,0,
 		   (hash_get_key) get_key_conn, (hash_free_key) free_user,
 		   0);
+#endif
 }
 
 
@@ -466,7 +466,6 @@
   (void) pthread_mutex_unlock(&LOCK_user_conn);
   DBUG_RETURN(error);
 }
-#endif /* NO_EMBEDDED_ACCESS_CHECKS */
 
 /*
   Decrease user connection count
@@ -500,13 +499,18 @@
   DBUG_VOID_RETURN;
 }
 
+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
+
 
 void free_max_user_conn(void)
 {
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
   hash_free(&hash_user_connections);
+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
 }
 
 
+
 /*
   Mark all commands that somehow changes a table
   This is used to check number of updates / hour
@@ -1476,9 +1480,11 @@
     }
     else
     {
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
       /* we've authenticated new user */
       if (save_user_connect)
 	decrease_user_connections(save_user_connect);
+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
       x_free((gptr) save_db);
       x_free((gptr) save_user);
     }

--- 1.14/include/sql_common.h	Fri Oct 15 23:03:07 2004
+++ 1.15/include/sql_common.h	Thu Jun  1 17:05:55 2006
@@ -33,7 +33,8 @@
 my_bool
 cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
 		     const char *header, ulong header_length,
-		     const char *arg, ulong arg_length, my_bool skip_check);
+		     const char *arg, ulong arg_length, my_bool skip_check,
+                     MYSQL_STMT *stmt);
 
 void set_stmt_errmsg(MYSQL_STMT * stmt, const char *err, int errcode,
 		     const char *sqlstate);

--- 1.88/sql-common/client.c	Mon Nov 21 16:08:39 2005
+++ 1.89/sql-common/client.c	Thu Jun  1 17:05:55 2006
@@ -648,7 +648,8 @@
 my_bool
 cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
 		     const char *header, ulong header_length,
-		     const char *arg, ulong arg_length, my_bool skip_check)
+		     const char *arg, ulong arg_length, my_bool skip_check,
+                     MYSQL_STMT *stmt __attribute__((unused)))
 {
   NET *net= &mysql->net;
   my_bool result= 1;

--- 1.12/libmysqld/embedded_priv.h	Mon May 17 12:05:30 2004
+++ 1.13/libmysqld/embedded_priv.h	Thu Jun  1 17:05:55 2006
@@ -24,9 +24,9 @@
 
 C_MODE_START
 void lib_connection_phase(NET *net, int phase);
-void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db);
-void *create_embedded_thd(int client_flag, char *db);
-int check_embedded_connection(MYSQL *mysql);
+void init_embedded_mysql(MYSQL *mysql, int client_flag);
+void *create_embedded_thd(int client_flag);
+int check_embedded_connection(MYSQL *mysql, const char *db);
 void free_old_query(MYSQL *mysql);
 void embedded_get_error(MYSQL *mysql);
 extern MYSQL_METHODS embedded_methods;

--- 1.125/libmysqld/lib_sql.cc	Wed Sep 28 00:35:58 2005
+++ 1.126/libmysqld/lib_sql.cc	Thu Jun  1 17:05:55 2006
@@ -47,6 +47,7 @@
 #include "errmsg.h"
 #include <sql_common.h>
 
+
 void embedded_get_error(MYSQL *mysql)
 {
   THD *thd=(THD *) mysql->thd;
@@ -66,7 +67,8 @@
 static my_bool
 emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
 		     const char *header, ulong header_length,
-		     const char *arg, ulong arg_length, my_bool skip_check)
+		     const char *arg, ulong arg_length, my_bool skip_check,
+                     MYSQL_STMT *stmt)
 {
   my_bool result= 1;
   THD *thd=(THD *) mysql->thd;
@@ -90,6 +92,7 @@
   mysql->affected_rows= ~(my_ulonglong) 0;
   mysql->field_count= 0;
   net->last_errno= 0;
+  mysql->current_stmt= stmt;
 
   thd->store_globals();				// Fix if more than one connect
   /* 
@@ -183,7 +186,6 @@
       mysql->server_status|= SERVER_STATUS_IN_TRANS;
 
     stmt->fields= mysql->fields;
-    stmt->mem_root= mysql->field_alloc;
     mysql->fields= NULL;
   }
 
@@ -225,7 +227,7 @@
   thd->client_param_count= stmt->param_count;
   thd->client_params= stmt->params;
   if (emb_advanced_command(stmt->mysql, COM_EXECUTE,0,0,
-                           header, sizeof(header), 1) ||
+                           header, sizeof(header), 1, stmt) ||
       emb_mysql_read_query_result(stmt->mysql))
   {
     NET *net= &stmt->mysql->net;
@@ -242,8 +244,6 @@
   MYSQL_DATA *data;
   if (!(data= emb_read_rows(stmt->mysql, 0, 0)))
     return 1;
-  stmt->result= *data;
-  my_free((char *) data, MYF(0));
   return 0;
 }
 
@@ -298,7 +298,8 @@
   DBUG_ENTER("emb_next_result");
 
   if (emb_advanced_command(mysql, COM_QUERY,0,0,
-			   thd->query_rest.ptr(),thd->query_rest.length(),1) ||
+			   thd->query_rest.ptr(),
+                           thd->query_rest.length(),1, 0) ||
       emb_mysql_read_query_result(mysql))
     DBUG_RETURN(1);
 
@@ -482,14 +483,14 @@
 } /* extern "C" */
 
 C_MODE_START
-void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db)
+void init_embedded_mysql(MYSQL *mysql, int client_flag)
 {
   THD *thd = (THD *)mysql->thd;
   thd->mysql= mysql;
   mysql->server_version= server_version;
 }
 
-void *create_embedded_thd(int client_flag, char *db)
+void *create_embedded_thd(int client_flag)
 {
   THD * thd= new THD;
   thd->thread_id= thread_id++;
@@ -515,8 +516,8 @@
   thd->init_for_queries();
   thd->client_capabilities= client_flag;
 
-  thd->db= db;
-  thd->db_length= db ? strip_sp(db) : 0;
+  thd->db= NULL;
+  thd->db_length= 0;
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
   thd->db_access= DB_ACLS;
   thd->master_access= ~NO_ACCESS;
@@ -533,18 +534,18 @@
 }
 
 #ifdef NO_EMBEDDED_ACCESS_CHECKS
-int check_embedded_connection(MYSQL *mysql)
+int check_embedded_connection(MYSQL *mysql, const char *db)
 {
   THD *thd= (THD*)mysql->thd;
   thd->host= (char*)my_localhost;
   thd->host_or_ip= thd->host;
   thd->user= my_strdup(mysql->user, MYF(0));
   thd->priv_user= thd->user;
-  return check_user(thd, COM_CONNECT, NULL, 0, thd->db, true);
+  return check_user(thd, COM_CONNECT, NULL, 0, db, true);
 }
 
 #else
-int check_embedded_connection(MYSQL *mysql)
+int check_embedded_connection(MYSQL *mysql, const char *db)
 {
   THD *thd= (THD*)mysql->thd;
   int result;
@@ -578,7 +579,7 @@
     passwd_len= 0;
 
   if((result= check_user(thd, COM_CONNECT, 
-			 scramble_buff, passwd_len, thd->db, true)))
+			 scramble_buff, passwd_len, db, true)))
      goto err;
 
   return 0;
@@ -636,8 +637,9 @@
     DBUG_RETURN(0);
 
   field_count= list->elements;
-  field_alloc= &mysql->field_alloc;
-  if (!(client_field= thd->mysql->fields= 
+  field_alloc= mysql->current_stmt ? &mysql->current_stmt->mem_root :
+                                     &mysql->field_alloc;
+  if (!(client_field= mysql->fields= 
 	(MYSQL_FIELD *)alloc_root(field_alloc, 
 				  sizeof(MYSQL_FIELD) * field_count)))
     goto err;
@@ -707,7 +709,7 @@
     client_field->max_length= 0;
     ++client_field;
   }
-  thd->mysql->field_count= field_count;
+  mysql->field_count= field_count;
 
   DBUG_RETURN(prepare_for_send(list));
  err:
@@ -736,13 +738,20 @@
 
   if (!data)
   {
-    if (!(data= (MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
-					MYF(MY_WME | MY_ZEROFILL))))
-      return true;
+    MYSQL *mysql= thd->mysql;
+
+    if (mysql->current_stmt)
+      data= &mysql->current_stmt->result;
+    else
+    {
+      if (!(data= (MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
+                                          MYF(MY_WME | MY_ZEROFILL))))
+        return true;
     
+      init_alloc_root(&data->alloc,8192,0);	/* Assume rowlength < 8192 */
+      data->alloc.min_malloc=sizeof(MYSQL_ROWS);
+    }
     alloc= &data->alloc;
-    init_alloc_root(alloc,8192,0);	/* Assume rowlength < 8192 */
-    alloc->min_malloc=sizeof(MYSQL_ROWS);
     data->rows=0;
     data->fields=field_count;
     data->prev_ptr= &data->data;

--- 1.65/libmysqld/libmysqld.c	Thu Aug  4 13:28:51 2005
+++ 1.66/libmysqld/libmysqld.c	Thu Jun  1 17:05:55 2006
@@ -134,7 +134,6 @@
 		   const char *passwd, const char *db,
 		   uint port, const char *unix_socket,ulong client_flag)
 {
-  char *db_name;
   char name_buff[USERNAME_LENGTH];
 
   DBUG_ENTER("mysql_real_connect");
@@ -197,13 +196,11 @@
 
   port=0;
   unix_socket=0;
-  db_name = db ? my_strdup(db,MYF(MY_WME)) : NULL;
+  mysql->thd= create_embedded_thd(client_flag);
 
-  mysql->thd= create_embedded_thd(client_flag, db_name);
+  init_embedded_mysql(mysql, client_flag);
 
-  init_embedded_mysql(mysql, client_flag, db_name);
-
-  if (check_embedded_connection(mysql))
+  if (check_embedded_connection(mysql, db))
     goto error;
 
   if (mysql_init_charset(mysql))
Thread
bk commit into 4.1 tree (holyfoot:1.2490) BUG#16017holyfoot1 Jun