List:Commits« Previous MessageNext Message »
From:konstantin Date:October 31 2007 9:11pm
Subject:bk commit into 5.1 tree (kostja:1.2599) BUG#12713
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of kostja. When kostja 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@stripped, 2007-11-01 00:10:58+03:00, kostja@bodhi.(none) +6 -0
  Remove net_printf_error(). Do not talk to network directly in
  check_user()/check_connection()/check_for_max_user_connections().
  
  This is a pre-requisite patch for the fix for Bug#12713 "Error in a stored 
  function called from a SELECT doesn't cause ROLLBACK of statem"
  
  Implement review comments.

  sql/mysql_priv.h@stripped, 2007-11-01 00:10:56+03:00, kostja@bodhi.(none) +0 -1
    check_for_max_user_connections() is used in one place only, make it static.

  sql/mysqld.cc@stripped, 2007-11-01 00:10:56+03:00, kostja@bodhi.(none) +5 -1
    Remove net_printf_error(): a consolidation of error reporting facilities
    is necessary to simplify maintenance of the query cache, the 
    client-server protocol, stored procedure continue handlers. 
    Rewrite the only place where its use is somewhat justified 
    (my_error() can not be used since we need to report an error for the thread 
    that does not exist) with my_snprintf()/net_send_error().

  sql/protocol.cc@stripped, 2007-11-01 00:10:56+03:00, kostja@bodhi.(none) +1 -119
    Remove net_printf_error().

  sql/protocol.h@stripped, 2007-11-01 00:10:56+03:00, kostja@bodhi.(none) +0 -1
    Remove net_printf_error().

  sql/sql_connect.cc@stripped, 2007-11-01 00:10:56+03:00, kostja@bodhi.(none) +104 -83
    Remove net_printf_error(). In check_connection()/check_user()/
    check_for_max_user_connections() do not write directly to the network,
    but use the standard my_error() mechanism to record an error in THD.
    It will be sent to the client by the caller. This was the last place
    in the server that would attempt to send an error directly, mainly left 
    untouched by 5.0 refactoring because it is executed only during 
    thread startup.

  sql/sql_parse.cc@stripped, 2007-11-01 00:10:56+03:00, kostja@bodhi.(none) +0 -5
    In the old code, when res was greater than 0, it contained an exact 
    error code, e.g. ER_OUT_OF_RESOURCES or NO SUCH DATABASE, 
    or ER_HANDSHAKE_ERROR. I don't know the reason why this error code was 
    ignored, and instead a generic  ER_UNKNOWN_COM_ERROR was pushed into the
    error stack, but knowing the relaxed attitude towards preserving the error
    codes in the old code, I'm inclinded to think that it was a bug.
    
    After this patch, the most specific error message is already pushed,
    so calling my_message() again is useless.
    
    If res is < 0, the error used to be already sent. This is not done
    by the new code, but will be done later, in the end
    of dispatch_command(). When this is done, clear_error() will be called 
    for us - it is in the first lines of do_command.
    
    To sum up, this change is to remove COM_CHANGE_USER specific error handling
    in favor of the standard one employed for all other COM_* commands.

diff -Nrup a/sql/mysql_priv.h b/sql/mysql_priv.h
--- a/sql/mysql_priv.h	2007-10-29 17:07:15 +03:00
+++ b/sql/mysql_priv.h	2007-11-01 00:10:56 +03:00
@@ -920,7 +920,6 @@ bool init_new_connection_handler_thread(
 void reset_mqh(LEX_USER *lu, bool get_them);
 bool check_mqh(THD *thd, uint check_command);
 void time_out_user_resource_limits(THD *thd, USER_CONN *uc);
-int check_for_max_user_connections(THD *thd, USER_CONN *uc);
 void decrease_user_connections(USER_CONN *uc);
 void thd_init_client_charset(THD *thd, uint cs_number);
 bool setup_connection_thread_globals(THD *thd);
diff -Nrup a/sql/mysqld.cc b/sql/mysqld.cc
--- a/sql/mysqld.cc	2007-10-30 22:35:11 +03:00
+++ b/sql/mysqld.cc	2007-11-01 00:10:56 +03:00
@@ -4302,6 +4302,7 @@ void create_thread_to_handle_connection(
   }
   else
   {
+    char error_message_buff[MYSQL_ERRMSG_SIZE];
     /* Create new thread to handle connection */
     int error;
     thread_created++;
@@ -4320,7 +4321,10 @@ void create_thread_to_handle_connection(
       thd->killed= THD::KILL_CONNECTION;			// Safety
       (void) pthread_mutex_unlock(&LOCK_thread_count);
       statistic_increment(aborted_connects,&LOCK_status);
-      net_printf_error(thd, ER_CANT_CREATE_THREAD, error);
+      /* Can't use my_error() since store_globals has not been called. */
+      my_snprintf(error_message_buff, sizeof(error_message_buff),
+                  ER(ER_CANT_CREATE_THREAD), error);
+      net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff);
       (void) pthread_mutex_lock(&LOCK_thread_count);
       close_connection(thd,0,0);
       delete thd;
diff -Nrup a/sql/protocol.cc b/sql/protocol.cc
--- a/sql/protocol.cc	2007-10-29 17:07:15 +03:00
+++ b/sql/protocol.cc	2007-11-01 00:10:56 +03:00
@@ -58,7 +58,7 @@ bool Protocol_binary::net_store_data(con
 
    Design note:
 
-   net_printf_error and net_send_error are low-level functions
+   net_send_error is a low-level functions
    that shall be used only when a new connection is being
    established or at server startup.
    For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
@@ -120,124 +120,6 @@ void net_send_error(THD *thd, uint sql_e
   DBUG_VOID_RETURN;
 }
 
-/*
-   Write error package and flush to client
-   It's a little too low level, but I don't want to use another buffer for
-   this
-
-   Design note:
-
-   net_printf_error and net_send_error are low-level functions
-   that shall be used only when a new connection is being
-   established or at server startup.
-   For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
-   critical that every error that can be intercepted is issued in one
-   place only, my_message_sql.
-*/
-
-void
-net_printf_error(THD *thd, uint errcode, ...)
-{
-  va_list args;
-  uint length,offset;
-  const char *format;
-#ifndef EMBEDDED_LIBRARY
-  const char *text_pos;
-  int head_length= NET_HEADER_SIZE;
-#else
-  char text_pos[1024];
-#endif
-  NET *net= &thd->net;
-
-  DBUG_ENTER("net_printf_error");
-  DBUG_PRINT("enter",("message: %u",errcode));
-
-  DBUG_ASSERT(!thd->spcont);
-
-  if (net && net->no_send_error)
-  {
-    thd->clear_error();
-    thd->is_fatal_error= 0;			// Error message is given
-    DBUG_PRINT("info", ("sending error messages prohibited"));
-    DBUG_VOID_RETURN;
-  }
-
-  thd->is_slave_error=  1; // needed to catch query errors during replication
-#ifndef EMBEDDED_LIBRARY
-  query_cache_abort(net);	// Safety
-#endif
-  va_start(args,errcode);
-  /*
-    The following is needed to make net_printf_error() work with 0 argument
-    for errorcode and use the argument after that as the format string. This
-    is useful for rare errors that are not worth the hassle to put in
-    errmsg.sys, but at the same time, the message is not fixed text
-  */
-  if (errcode)
-    format= ER(errcode);
-  else
-  {
-    format=va_arg(args,char*);
-    errcode= ER_UNKNOWN_ERROR;
-  }
-  offset= (net->return_errno ?
-	   ((thd->client_capabilities & CLIENT_PROTOCOL_41) ?
-	    2+SQLSTATE_LENGTH+1 : 2) : 0);
-#ifndef EMBEDDED_LIBRARY
-  text_pos=(char*) net->buff + head_length + offset + 1;
-  length= (uint) ((char*)net->buff_end - text_pos);
-#else
-  length=sizeof(text_pos)-1;
-#endif
-  length=my_vsnprintf(my_const_cast(char*) (text_pos),
-                      min(length, sizeof(net->last_error)),
-                      format,args);
-  va_end(args);
-
-  /* Replication slave relies on net->last_* to see if there was error */
-  net->last_errno= errcode;
-  strmake(net->last_error, text_pos, sizeof(net->last_error)-1);
-
-#ifndef EMBEDDED_LIBRARY
-  if (net->vio == 0)
-  {
-    if (thd->bootstrap)
-    {
-      /*
-	In bootstrap it's ok to print on stderr
-	This may also happen when we get an error from a slave thread
-      */
-      fprintf(stderr,"ERROR: %d  %s\n",errcode,text_pos);
-      thd->fatal_error();
-    }
-    DBUG_VOID_RETURN;
-  }
-
-  int3store(net->buff,length+1+offset);
-  net->buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++);
-  net->buff[head_length]=(uchar) 255;		// Error package
-  if (offset)
-  {
-    uchar *pos= net->buff+head_length+1;
-    int2store(pos, errcode);
-    if (thd->client_capabilities & CLIENT_PROTOCOL_41)
-    {
-      pos[2]= '#';      /* To make the protocol backward compatible */
-      memcpy(pos+3, mysql_errno_to_sqlstate(errcode), SQLSTATE_LENGTH);
-    }
-  }
-  VOID(net_real_write(net, net->buff, length+head_length+1+offset));
-#else
-  net->last_errno= errcode;
-  strmake(net->last_error, text_pos, length);
-  strmake(net->sqlstate, mysql_errno_to_sqlstate(errcode), SQLSTATE_LENGTH);
-#endif
-  if (thd->killed != THD::KILL_CONNECTION)
-    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, errcode,
-                 text_pos ? text_pos : ER(errcode));
-  thd->is_fatal_error=0;			// Error message is given
-  DBUG_VOID_RETURN;
-}
 
 /*
   Return ok to the client.
diff -Nrup a/sql/protocol.h b/sql/protocol.h
--- a/sql/protocol.h	2007-05-24 02:39:21 +04:00
+++ b/sql/protocol.h	2007-11-01 00:10:56 +03:00
@@ -172,7 +172,6 @@ public:
 };
 
 void send_warning(THD *thd, uint sql_errno, const char *err=0);
-void net_printf_error(THD *thd, uint sql_errno, ...);
 void net_send_error(THD *thd, uint sql_errno=0, const char *err=0);
 void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L,
 	     const char *info=0);
diff -Nrup a/sql/sql_connect.cc b/sql/sql_connect.cc
--- a/sql/sql_connect.cc	2007-10-30 20:10:08 +03:00
+++ b/sql/sql_connect.cc	2007-11-01 00:10:56 +03:00
@@ -87,7 +87,7 @@ static int get_or_create_user_conn(THD *
 	       my_malloc(sizeof(struct user_conn) + temp_len+1,
 			 MYF(MY_WME)))))
     {
-      net_send_error(thd, 0, NullS);		// Out of memory
+      /* MY_WME ensures an error is set in THD. */
       return_val= 1;
       goto end;
     }
@@ -100,8 +100,8 @@ static int get_or_create_user_conn(THD *
     uc->reset_utime= thd->thr_create_utime;
     if (my_hash_insert(&hash_user_connections, (uchar*) uc))
     {
+      /* The only possible error is out of memory, MY_WME sets an error. */
       my_free((char*) uc,0);
-      net_send_error(thd, 0, NullS);		// Out of memory
       return_val= 1;
       goto end;
     }
@@ -132,6 +132,7 @@ end:
     1	error
 */
 
+static
 int check_for_max_user_connections(THD *thd, USER_CONN *uc)
 {
   int error=0;
@@ -141,7 +142,7 @@ int check_for_max_user_connections(THD *
   if (max_user_connections && !uc->user_resources.user_conn &&
       max_user_connections < (uint) uc->connections)
   {
-    net_printf_error(thd, ER_TOO_MANY_USER_CONNECTIONS, uc->user);
+    my_error(ER_TOO_MANY_USER_CONNECTIONS, MYF(0), uc->user);
     error=1;
     goto end;
   }
@@ -149,24 +150,24 @@ int check_for_max_user_connections(THD *
   if (uc->user_resources.user_conn &&
       uc->user_resources.user_conn < uc->connections)
   {
-    net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user,
-                     "max_user_connections",
-                     (long) uc->user_resources.user_conn);
+    my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user,
+             "max_user_connections",
+             (long) uc->user_resources.user_conn);
     error= 1;
     goto end;
   }
   if (uc->user_resources.conn_per_hour &&
       uc->user_resources.conn_per_hour <= uc->conn_per_hour)
   {
-    net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user,
-                     "max_connections_per_hour",
-                     (long) uc->user_resources.conn_per_hour);
+    my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user,
+             "max_connections_per_hour",
+             (long) uc->user_resources.conn_per_hour);
     error=1;
     goto end;
   }
   uc->conn_per_hour++;
 
-  end:
+end:
   if (error)
     uc->connections--; // no need for decrease_user_connections() here
   (void) pthread_mutex_unlock(&LOCK_user_conn);
@@ -258,8 +259,8 @@ bool check_mqh(THD *thd, uint check_comm
   if (uc->user_resources.questions &&
       uc->questions++ >= uc->user_resources.questions)
   {
-    net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_questions",
-                     (long) uc->user_resources.questions);
+    my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user, "max_questions",
+             (long) uc->user_resources.questions);
     error=1;
     goto end;
   }
@@ -270,8 +271,8 @@ bool check_mqh(THD *thd, uint check_comm
         (sql_command_flags[check_command] & CF_CHANGES_DATA) &&
 	uc->updates++ >= uc->user_resources.updates)
     {
-      net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_updates",
-                       (long) uc->user_resources.updates);
+      my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user, "max_updates",
+               (long) uc->user_resources.updates);
       error=1;
       goto end;
     }
@@ -284,33 +285,33 @@ end:
 #endif /* NO_EMBEDDED_ACCESS_CHECKS */
 
 
-/*
-  Check if user exist and password supplied is correct. 
+/**
+  Check if user exist and password supplied is correct.
 
-  SYNOPSIS
-    check_user()
-    thd          thread handle, thd->security_ctx->{host,user,ip} are used
-    command      originator of the check: now check_user is called
-                 during connect and change user procedures; used for 
-                 logging.
-    passwd       scrambled password received from client
-    passwd_len   length of scrambled password
-    db           database name to connect to, may be NULL
-    check_count  dont know exactly
-
-    Note, that host, user and passwd may point to communication buffer.
-    Current implementation does not depend on that, but future changes
-    should be done with this in mind; 'thd' is INOUT, all other params
-    are 'IN'.
-
-  RETURN VALUE
-    0  OK; thd->security_ctx->user/master_access/priv_user/db_access and
-       thd->db are updated; OK is sent to client;
-   -1  access denied or handshake error; error is sent to client;
-   >0  error, not sent to client
+  @param  thd         thread handle, thd->security_ctx->{host,user,ip} are used
+  @param  command     originator of the check: now check_user is called
+                      during connect and change user procedures; used for
+                      logging.
+  @param  passwd      scrambled password received from client
+  @param  passwd_len  length of scrambled password
+  @param  db          database name to connect to, may be NULL
+  @param  check_count TRUE if establishing a new connection. In this case
+                      check that we have not exceeded the global
+                      max_connections limist
+
+  @note Host, user and passwd may point to communication buffer.
+  Current implementation does not depend on that, but future changes
+  should be done with this in mind; 'thd' is INOUT, all other params
+  are 'IN'.
+
+  @retval  0  OK; thd->security_ctx->user/master_access/priv_user/db_access and
+              thd->db are updated; OK is sent to the client.
+  @retval  1  error, e.g. access denied or handshake error, not sent to
+              the client. A message is pushed into the error stack.
 */
 
-int check_user(THD *thd, enum enum_server_command command, 
+int
+check_user(THD *thd, enum enum_server_command command,
 	       const char *passwd, uint passwd_len, const char *db,
 	       bool check_count)
 {
@@ -328,11 +329,7 @@ int check_user(THD *thd, enum enum_serve
     */
     thd->reset_db(NULL, 0);
     if (mysql_change_db(thd, &db_str, FALSE))
-    {
-      /* Send the error to the client */
-      net_send_error(thd);
-      DBUG_RETURN(-1);
-    }
+      DBUG_RETURN(1);
   }
   send_ok(thd);
   DBUG_RETURN(0);
@@ -349,14 +346,17 @@ int check_user(THD *thd, enum enum_serve
   */
   if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323)
   {
-    net_printf_error(thd, ER_NOT_SUPPORTED_AUTH_MODE);
+    my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
     general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
-    DBUG_RETURN(-1);
+    DBUG_RETURN(1);
   }
   if (passwd_len != 0 &&
       passwd_len != SCRAMBLE_LENGTH &&
       passwd_len != SCRAMBLE_LENGTH_323)
-    DBUG_RETURN(ER_HANDSHAKE_ERROR);
+  {
+    my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
+    DBUG_RETURN(1);
+  }
 
   /*
     Clear thd->db as it points to something, that will be freed when 
@@ -380,20 +380,21 @@ int check_user(THD *thd, enum enum_serve
     NET *net= &thd->net;
     if (opt_secure_auth_local)
     {
-      net_printf_error(thd, ER_SERVER_IS_IN_SECURE_AUTH_MODE,
-                       thd->main_security_ctx.user,
-                       thd->main_security_ctx.host_or_ip);
+      my_error(ER_SERVER_IS_IN_SECURE_AUTH_MODE, MYF(0),
+               thd->main_security_ctx.user,
+               thd->main_security_ctx.host_or_ip);
       general_log_print(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE),
                         thd->main_security_ctx.user,
                         thd->main_security_ctx.host_or_ip);
-      DBUG_RETURN(-1);
+      DBUG_RETURN(1);
     }
     /* We have to read very specific packet size */
     if (send_old_password_request(thd) ||
         my_net_read(net) != SCRAMBLE_LENGTH_323 + 1)
     {
       inc_host_errors(&thd->remote.sin_addr);
-      DBUG_RETURN(ER_HANDSHAKE_ERROR);
+      my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
+      DBUG_RETURN(1);
     }
     /* Final attempt to check the user based on reply */
     /* So as passwd is short, errcode is always >= 0 */
@@ -427,8 +428,8 @@ int check_user(THD *thd, enum enum_serve
         VOID(pthread_mutex_unlock(&LOCK_thread_count));
         if (!count_ok)
         {                                         // too many connections
-          net_send_error(thd, ER_CON_COUNT_ERROR);
-          DBUG_RETURN(-1);
+          my_error(ER_CON_COUNT_ERROR, MYF(0));
+          DBUG_RETURN(1);
         }
       }
 
@@ -462,24 +463,29 @@ int check_user(THD *thd, enum enum_serve
             (opt_old_style_user_limits ? thd->main_security_ctx.host_or_ip :
              thd->main_security_ctx.priv_host),
             &ur))
-	DBUG_RETURN(-1);
+      {
+        /* The error is set by get_or_create_user_conn(). */
+	DBUG_RETURN(1);
+      }
       if (thd->user_connect &&
 	  (thd->user_connect->user_resources.conn_per_hour ||
 	   thd->user_connect->user_resources.user_conn ||
 	   max_user_connections) &&
 	  check_for_max_user_connections(thd, thd->user_connect))
-	DBUG_RETURN(-1);
+      {
+        /* The error is set in check_for_max_user_connections(). */
+        DBUG_RETURN(1);
+      }
 
       /* Change database if necessary */
       if (db && db[0])
       {
         if (mysql_change_db(thd, &db_str, FALSE))
         {
-          /* Send error to the client */
-          net_send_error(thd);
+          /* mysql_change_db() has pushed the error message. */
           if (thd->user_connect)
             decrease_user_connections(thd->user_connect);
-          DBUG_RETURN(-1);
+          DBUG_RETURN(1);
         }
       }
       send_ok(thd);
@@ -490,19 +496,19 @@ int check_user(THD *thd, enum enum_serve
   }
   else if (res == 2) // client gave short hash, server has long hash
   {
-    net_printf_error(thd, ER_NOT_SUPPORTED_AUTH_MODE);
+    my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
     general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
-    DBUG_RETURN(-1);
+    DBUG_RETURN(1);
   }
-  net_printf_error(thd, ER_ACCESS_DENIED_ERROR,
-                   thd->main_security_ctx.user,
-                   thd->main_security_ctx.host_or_ip,
-                   passwd_len ? ER(ER_YES) : ER(ER_NO));
+  my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
+           thd->main_security_ctx.user,
+           thd->main_security_ctx.host_or_ip,
+           passwd_len ? ER(ER_YES) : ER(ER_NO));
   general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR),
                     thd->main_security_ctx.user,
                     thd->main_security_ctx.host_or_ip,
                     passwd_len ? ER(ER_YES) : ER(ER_NO));
-  DBUG_RETURN(-1);
+  DBUG_RETURN(1);
 #endif /* NO_EMBEDDED_ACCESS_CHECKS */
 }
 
@@ -666,9 +672,12 @@ static int check_connection(THD *thd)
     char ip[30];
 
     if (vio_peer_addr(net->vio, ip, &thd->peer_port))
-      return (ER_BAD_HOST_ERROR);
-    if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(0))))
-      return (ER_OUT_OF_RESOURCES);
+    {
+      my_error(ER_BAD_HOST_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
+      return 1;
+    }
+    if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(MY_WME))))
+      return 1; /* The error is set by my_strdup(). */
     thd->main_security_ctx.host_or_ip= thd->main_security_ctx.ip;
     vio_in_addr(net->vio,&thd->remote.sin_addr);
     if (!(specialflag & SPECIAL_NO_RESOLVE))
@@ -685,7 +694,10 @@ static int check_connection(THD *thd)
         thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
       }
       if (connect_errors > max_connect_errors)
-        return(ER_HOST_IS_BLOCKED);
+      {
+        my_error(ER_HOST_IS_BLOCKED, MYF(0), thd->main_security_ctx.host_or_ip);
+        return 1;
+      }
     }
     DBUG_PRINT("info",("Host: %s  ip: %s",
 		       (thd->main_security_ctx.host ?
@@ -693,7 +705,11 @@ static int check_connection(THD *thd)
 		       (thd->main_security_ctx.ip ?
                         thd->main_security_ctx.ip : "unknown ip")));
     if (acl_check_host(thd->main_security_ctx.host, thd->main_security_ctx.ip))
-      return(ER_HOST_NOT_PRIVILEGED);
+    {
+      my_error(ER_HOST_NOT_PRIVILEGED, MYF(0),
+               thd->main_security_ctx.host_or_ip);
+      return 1;
+    }
   }
   else /* Hostname given means that the connection was on a socket */
   {
@@ -753,7 +769,9 @@ static int check_connection(THD *thd)
 	pkt_len < MIN_HANDSHAKE_SIZE)
     {
       inc_host_errors(&thd->remote.sin_addr);
-      return(ER_HANDSHAKE_ERROR);
+      my_error(ER_HANDSHAKE_ERROR, MYF(0),
+               thd->main_security_ctx.host_or_ip);
+      return 1;
     }
   }
 #ifdef _CUSTOMCONFIG_
@@ -762,7 +780,7 @@ static int check_connection(THD *thd)
   if (connect_errors)
     reset_host_errors(&thd->remote.sin_addr);
   if (thd->packet.alloc(thd->variables.net_buffer_length))
-    return(ER_OUT_OF_RESOURCES);
+    return 1; /* The error is set by alloc(). */
 
   thd->client_capabilities=uint2korr(net->read_pos);
   if (thd->client_capabilities & CLIENT_PROTOCOL_41)
@@ -790,14 +808,16 @@ static int check_connection(THD *thd)
     if (!ssl_acceptor_fd)
     {
       inc_host_errors(&thd->remote.sin_addr);
-      return(ER_HANDSHAKE_ERROR);
+      my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
+      return 1;
     }
     DBUG_PRINT("info", ("IO layer change in progress..."));
     if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout))
     {
       DBUG_PRINT("error", ("Failed to accept new SSL connection"));
       inc_host_errors(&thd->remote.sin_addr);
-      return(ER_HANDSHAKE_ERROR);
+      my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
+      return 1;
     }
     DBUG_PRINT("info", ("Reading user information over SSL layer"));
     if ((pkt_len= my_net_read(net)) == packet_error ||
@@ -806,7 +826,8 @@ static int check_connection(THD *thd)
       DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
 			   pkt_len));
       inc_host_errors(&thd->remote.sin_addr);
-      return(ER_HANDSHAKE_ERROR);
+      my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
+      return 1;
     }
   }
 #endif /* HAVE_OPENSSL */
@@ -814,7 +835,8 @@ static int check_connection(THD *thd)
   if (end >= (char*) net->read_pos+ pkt_len +2)
   {
     inc_host_errors(&thd->remote.sin_addr);
-    return(ER_HANDSHAKE_ERROR);
+    my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
+    return 1;
   }
 
   if (thd->client_capabilities & CLIENT_INTERACTIVE)
@@ -851,7 +873,8 @@ static int check_connection(THD *thd)
   if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len)
   {
     inc_host_errors(&thd->remote.sin_addr);
-    return ER_HANDSHAKE_ERROR;
+    my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
+    return 1;
   }
 
   /* Since 4.1 all database names are stored in utf8 */
@@ -879,8 +902,8 @@ static int check_connection(THD *thd)
 
   if (thd->main_security_ctx.user)
     x_free(thd->main_security_ctx.user);
-  if (!(thd->main_security_ctx.user= my_strdup(user, MYF(0))))
-    return (ER_OUT_OF_RESOURCES);
+  if (!(thd->main_security_ctx.user= my_strdup(user, MYF(MY_WME))))
+    return 1; /* The error is set by my_strdup(). */
   return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE);
 }
 
@@ -929,7 +952,6 @@ bool setup_connection_thread_globals(THD
 
 bool login_connection(THD *thd)
 {
-  int error;
   NET *net= &thd->net;
   Security_context *sctx= thd->security_ctx;
   DBUG_ENTER("login_connection");
@@ -942,10 +964,9 @@ bool login_connection(THD *thd)
   my_net_set_read_timeout(net, connect_timeout);
   my_net_set_write_timeout(net, connect_timeout);
 
-  if ((error=check_connection(thd)))
+  if (check_connection(thd))
   {						// Wrong permissions
-    if (error > 0)
-      net_printf_error(thd, error, sctx->host_or_ip);
+    net_send_error(thd);
 #ifdef __NT__
     if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
       my_sleep(1000);				/* must wait after eof() */
diff -Nrup a/sql/sql_parse.cc b/sql/sql_parse.cc
--- a/sql/sql_parse.cc	2007-10-30 20:08:12 +03:00
+++ b/sql/sql_parse.cc	2007-11-01 00:10:56 +03:00
@@ -915,11 +915,6 @@ bool dispatch_command(enum enum_server_c
 
     if (res)
     {
-      /* authentication failure, we shall restore old user */
-      if (res > 0)
-        my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
-      else
-        thd->clear_error();                     // Error already sent to client
       x_free(thd->security_ctx->user);
       *thd->security_ctx= save_security_ctx;
       thd->user_connect= save_user_connect;
Thread
bk commit into 5.1 tree (kostja:1.2599) BUG#12713konstantin31 Oct