List:Commits« Previous MessageNext Message »
From:Davi Arnaut Date:March 28 2008 3:18am
Subject:bk commit into 6.0 tree (davi:1.2610) BUG#15192
View as plain text  
Below is the list of changes that have just been committed into a local
6.0 repository of davi.  When davi 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, 2008-03-27 23:18:20-03:00, davi@stripped +16 -0
  Bug#15192 "fatal errors" are caught by handlers in stored procedures
  
  The problem is that fatal errors (e.g.: out of memory) were being
  caught by stored procedure exception handlers which could cause
  the execution to not be stopped due to a continue handler.
  
  The solution is to not call any exception handler if the error is
  fatal and send the fatal error to the client.

  include/my_sys.h@stripped, 2008-03-27 23:18:14-03:00, davi@stripped +1 -0
    Introduce ME_FATALERROR flag to signal that a error is fatal.

  mysql-test/r/sp-error.result@stripped, 2008-03-27 23:18:14-03:00, davi@stripped +11 -0
    Add test case result for Bug#15192

  mysql-test/t/sp-error.test@stripped, 2008-03-27 23:18:14-03:00, davi@stripped +21 -0
    Add test case for Bug#15192

  sql/ha_partition.cc@stripped, 2008-03-27 23:18:14-03:00, davi@stripped +1 -2
    Pass flag to signal fatal error instead of calling fatal_error.

  sql/item_func.cc@stripped, 2008-03-27 23:18:15-03:00, davi@stripped +7 -8
    Pass flag to signal fatal error instead of calling fatal_error.

  sql/item_subselect.cc@stripped, 2008-03-27 23:18:15-03:00, davi@stripped +3 -3
    Set error when allocation fails.

  sql/mysqld.cc@stripped, 2008-03-27 23:18:15-03:00, davi@stripped +5 -2
    Don't call stored procedure error handlers if the error
    is fatal. The THD handler is allowed to catch the error
    because it might be silencing any kind of error.

  sql/opt_sum.cc@stripped, 2008-03-27 23:18:15-03:00, davi@stripped +2 -4
    Pass flag to signal fatal error instead of calling fatal_error.

  sql/sp_head.cc@stripped, 2008-03-27 23:18:15-03:00, davi@stripped +2 -1
    Stop executing stored procedure if a fatal error was signaled.

  sql/sql_class.h@stripped, 2008-03-27 23:18:15-03:00, davi@stripped +5 -1
    A error must exist for it to be fatal. Pass flag to signal fatal
    error instead of calling fatal_error.

  sql/sql_insert.cc@stripped, 2008-03-27 23:18:15-03:00, davi@stripped +4 -7
    Pass flag to signal fatal error instead of calling fatal_error.

  sql/sql_parse.cc@stripped, 2008-03-27 23:18:15-03:00, davi@stripped +1 -2
    Pass flag to signal fatal error instead of calling fatal_error.

  sql/sql_partition.cc@stripped, 2008-03-27 23:18:16-03:00, davi@stripped +2 -6
    Pass flag to signal fatal error instead of calling fatal_error.

  sql/sql_select.cc@stripped, 2008-03-27 23:18:16-03:00, davi@stripped +2 -3
    Pass flag to signal fatal error instead of calling fatal_error.

  sql/sql_show.cc@stripped, 2008-03-27 23:18:16-03:00, davi@stripped +1 -2
    Pass flag to signal fatal error instead of calling fatal_error.

  sql/sql_update.cc@stripped, 2008-03-27 23:18:16-03:00, davi@stripped +10 -8
    Pass flag to signal fatal error instead of calling fatal_error.

diff -Nrup a/include/my_sys.h b/include/my_sys.h
--- a/include/my_sys.h	2008-02-27 07:03:14 -03:00
+++ b/include/my_sys.h	2008-03-27 23:18:14 -03:00
@@ -89,6 +89,7 @@ extern int NEAR my_errno;		/* Last error
 #define ME_COLOUR1	((1 << ME_HIGHBYTE))	/* Possibly error-colours */
 #define ME_COLOUR2	((2 << ME_HIGHBYTE))
 #define ME_COLOUR3	((3 << ME_HIGHBYTE))
+#define ME_FATALERROR   1024    /* Fatal statement error */
 
 	/* Bits in last argument to fn_format */
 #define MY_REPLACE_DIR		1	/* replace dir in name with 'dir' */
diff -Nrup a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
--- a/mysql-test/r/sp-error.result	2008-02-19 11:08:25 -03:00
+++ b/mysql-test/r/sp-error.result	2008-03-27 23:18:14 -03:00
@@ -1611,3 +1611,14 @@ end loop label1;
 end loop;
 end|
 ERROR 42000: End-label label1 without match
+drop procedure if exists p1;
+set @old_recursion_depth = @@max_sp_recursion_depth;
+set @@max_sp_recursion_depth = 255;
+create procedure p1(a int)
+begin
+declare continue handler for sqlexception select 'exception';
+call p1(a+1);
+end|
+call p1(1);
+set @@max_sp_recursion_depth = @old_recursion_depth;
+drop procedure p1;
diff -Nrup a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
--- a/mysql-test/t/sp-error.test	2008-02-19 11:08:36 -03:00
+++ b/mysql-test/t/sp-error.test	2008-03-27 23:18:14 -03:00
@@ -2372,6 +2372,27 @@ delimiter ;|
 #drop procedure p1;
 
 #
+# Bug#15192: "fatal errors" are caught by handlers in stored procedures
+#
+
+--disable_warnings
+drop procedure if exists p1;
+--enable_warnings
+set @old_recursion_depth = @@max_sp_recursion_depth;
+set @@max_sp_recursion_depth = 255;
+delimiter |;
+create procedure p1(a int)
+begin
+  declare continue handler for sqlexception select 'exception';
+  call p1(a+1);
+end|
+delimiter ;|
+--error 0,ER_STACK_OVERRUN_NEED_MORE
+call p1(1);
+set @@max_sp_recursion_depth = @old_recursion_depth;
+drop procedure p1;
+
+#
 # BUG#NNNN: New bug synopsis
 #
 #--disable_warnings
diff -Nrup a/sql/ha_partition.cc b/sql/ha_partition.cc
--- a/sql/ha_partition.cc	2008-03-27 15:58:37 -03:00
+++ b/sql/ha_partition.cc	2008-03-27 23:18:14 -03:00
@@ -1807,8 +1807,7 @@ partition_element *ha_partition::find_pa
       return part_elem;
   }
   DBUG_ASSERT(0);
-  my_error(ER_OUT_OF_RESOURCES, MYF(0));
-  current_thd->fatal_error();                   // Abort
+  my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
   return NULL;
 }
 
diff -Nrup a/sql/item_func.cc b/sql/item_func.cc
--- a/sql/item_func.cc	2008-03-27 15:58:37 -03:00
+++ b/sql/item_func.cc	2008-03-27 23:18:15 -03:00
@@ -3957,7 +3957,8 @@ update_hash(user_var_entry *entry, bool 
 	if (entry->value == pos)
 	  entry->value=0;
         entry->value= (char*) my_realloc(entry->value, length,
-                                         MYF(MY_ALLOW_ZERO_PTR | MY_WME));
+                                         MYF(MY_ALLOW_ZERO_PTR | MY_WME |
+                                             ME_FATALERROR));
         if (!entry->value)
 	  return 1;
       }
@@ -3994,7 +3995,6 @@ Item_func_set_user_var::update_hash(void
   if (::update_hash(entry, (null_value= args[0]->null_value),
                     ptr, length, res_type, cs, dv, unsigned_arg))
   {
-    current_thd->fatal_error();     // Probably end of memory
     null_value= 1;
     return 1;
   }
@@ -4685,6 +4685,7 @@ void Item_func_get_user_var::fix_length_
     max_length= MAX_BLOB_WIDTH;
   }
 
+  /* Might have been a logic error which is fatal. */
   if (error)
     thd->fatal_error();
 
@@ -4759,18 +4760,16 @@ bool Item_user_var_as_out_param::fix_fie
 
 void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs)
 {
-  if (::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs,
-                    DERIVATION_IMPLICIT, 0 /* unsigned_arg */))
-    current_thd->fatal_error();			// Probably end of memory
+  ::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs,
+                DERIVATION_IMPLICIT, 0 /* unsigned_arg */);
 }
 
 
 void Item_user_var_as_out_param::set_value(const char *str, uint length,
                                            CHARSET_INFO* cs)
 {
-  if (::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
-                    DERIVATION_IMPLICIT, 0 /* unsigned_arg */))
-    current_thd->fatal_error();			// Probably end of memory
+  ::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
+                DERIVATION_IMPLICIT, 0 /* unsigned_arg */);
 }
 
 
diff -Nrup a/sql/item_subselect.cc b/sql/item_subselect.cc
--- a/sql/item_subselect.cc	2008-03-12 05:25:22 -03:00
+++ b/sql/item_subselect.cc	2008-03-27 23:18:15 -03:00
@@ -2005,8 +2005,8 @@ subselect_union_engine::subselect_union_
   :subselect_engine(item_arg, result_arg)
 {
   unit= u;
-  if (!result_arg)				//out of memory
-    current_thd->fatal_error();
+  if (!result_arg)
+    my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
   unit->item= item_arg;
 }
 
@@ -2045,7 +2045,7 @@ int subselect_single_select_engine::prep
 		 select_lex->options | SELECT_NO_UNLOCK, result);
   if (!join || !result)
   {
-    thd->fatal_error();				//out of memory
+    my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
     return 1;
   }
   prepared= 1;
diff -Nrup a/sql/mysqld.cc b/sql/mysqld.cc
--- a/sql/mysqld.cc	2008-03-27 15:58:38 -03:00
+++ b/sql/mysqld.cc	2008-03-27 23:18:15 -03:00
@@ -2919,6 +2919,9 @@ int my_message_sql(uint error, const cha
   */
   if ((thd= current_thd))
   {
+    if (MyFlags & ME_FATALERROR)
+      thd->is_fatal_error= 1;
+
     mysql_audit_general(thd,MYSQL_AUDIT_GENERAL_ERROR,error,my_time(0),
                         0,0,str,str ? strlen(str) : 0,
                         thd->query,thd->query_length,
@@ -2966,7 +2969,7 @@ int my_message_sql(uint error, const cha
       If a continue handler is found, the error message will be cleared
       by the stored procedures code.
     */
-    if (thd->spcont &&
+    if (!thd->is_fatal_error && thd->spcont &&
         thd->spcont->handle_error(error, MYSQL_ERROR::WARN_LEVEL_ERROR, thd))
     {
       /*
@@ -2976,7 +2979,7 @@ int my_message_sql(uint error, const cha
       DBUG_RETURN(0);
     }
 
-    if (!thd->no_warnings_for_error)
+    if (!thd->no_warnings_for_error && !thd->is_fatal_error)
     {
       /*
         Suppress infinite recursion if there a memory allocation error
diff -Nrup a/sql/opt_sum.cc b/sql/opt_sum.cc
--- a/sql/opt_sum.cc	2007-12-21 17:27:44 -02:00
+++ b/sql/opt_sum.cc	2008-03-27 23:18:15 -03:00
@@ -174,8 +174,7 @@ int opt_sum_query(TABLE_LIST *tables, Li
       error= tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
       if(error)
       {
-        tl->table->file->print_error(error, MYF(0));
-        tl->table->in_use->fatal_error();
+        tl->table->file->print_error(error, MYF(ME_FATALERROR));
         return error;
       }
       count*= tl->table->file->stats.records;
@@ -423,8 +422,7 @@ int opt_sum_query(TABLE_LIST *tables, Li
 	    if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
 	      return HA_ERR_KEY_NOT_FOUND;	     // No rows matching WHERE
 	    /* HA_ERR_LOCK_DEADLOCK or some other error */
- 	    table->file->print_error(error, MYF(0));
-            table->in_use->fatal_error();
+            table->file->print_error(error, MYF(ME_FATALERROR));
             return(error);
 	  }
           removed_tables|= table->map;
diff -Nrup a/sql/sp_head.cc b/sql/sp_head.cc
--- a/sql/sp_head.cc	2008-03-27 08:26:12 -03:00
+++ b/sql/sp_head.cc	2008-03-27 23:18:15 -03:00
@@ -1262,7 +1262,7 @@ sp_head::execute(THD *thd)
 	continue;
       }
     }
-  } while (!err_status && !thd->killed);
+  } while (!err_status && !thd->killed && !thd->is_fatal_error);
 
 #if defined(ENABLED_PROFILING)
   thd->profiling.finish_current_query();
@@ -3943,6 +3943,7 @@ sp_add_to_query_tables(THD *thd, LEX *le
 
   if (!(table= (TABLE_LIST *)thd->calloc(sizeof(TABLE_LIST))))
   {
+    /* Out of memory error was set. */
     thd->fatal_error();
     return NULL;
   }
diff -Nrup a/sql/sql_class.h b/sql/sql_class.h
--- a/sql/sql_class.h	2008-03-27 15:58:38 -03:00
+++ b/sql/sql_class.h	2008-03-27 23:18:15 -03:00
@@ -1980,6 +1980,7 @@ public:
   */
   inline void fatal_error()
   {
+    DBUG_ASSERT(main_da.is_error());
     is_fatal_error= 1;
     DBUG_PRINT("error",("Fatal error set"));
   }
@@ -2137,7 +2138,10 @@ public:
     else
     {
       x_free(db);
-      db= new_db ? my_strndup(new_db, new_db_len, MYF(MY_WME)) : NULL;
+      if (new_db)
+        db= my_strndup(new_db, new_db_len, MYF(MY_WME | ME_FATALERROR));
+      else
+        db= NULL;
     }
     db_length= db ? new_db_len : 0;
     return new_db && !db;
diff -Nrup a/sql/sql_insert.cc b/sql/sql_insert.cc
--- a/sql/sql_insert.cc	2008-03-27 15:58:39 -03:00
+++ b/sql/sql_insert.cc	2008-03-27 23:18:15 -03:00
@@ -1872,19 +1872,18 @@ bool delayed_get_table(THD *thd, TABLE_L
     {
       if (!(di= new Delayed_insert()))
       {
-        thd->fatal_error();
+        my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
         goto end_create;
       }
       pthread_mutex_lock(&LOCK_thread_count);
       thread_count++;
       pthread_mutex_unlock(&LOCK_thread_count);
       di->thd.set_db(table_list->db, strlen(table_list->db));
-      di->thd.query= my_strdup(table_list->table_name, MYF(MY_WME));
+      di->thd.query= my_strdup(table_list->table_name, MYF(MY_WME |
ME_FATALERROR));
       if (di->thd.db == NULL || di->thd.query == NULL)
       {
         /* The error is reported */
 	delete di;
-        thd->fatal_error();
         goto end_create;
       }
       di->table_list= *table_list;			// Needed to open table
@@ -1902,8 +1901,7 @@ bool delayed_get_table(THD *thd, TABLE_L
 	pthread_mutex_unlock(&di->mutex);
 	di->unlock();
 	delete di;
-	my_error(ER_CANT_CREATE_THREAD, MYF(0), error);
-        thd->fatal_error();
+	my_error(ER_CANT_CREATE_THREAD, MYF(ME_FATALERROR), error);
         goto end_create;
       }
 
@@ -2302,8 +2300,7 @@ pthread_handler_t handle_delayed_insert(
   }
   if (!(di->table->file->ha_table_flags() & HA_CAN_INSERT_DELAYED))
   {
-    thd->fatal_error();
-    my_error(ER_ILLEGAL_HA, MYF(0), di->table_list.table_name);
+    my_error(ER_ILLEGAL_HA, MYF(ME_FATALERROR), di->table_list.table_name);
     goto err;
   }
   if (di->table->triggers)
diff -Nrup a/sql/sql_parse.cc b/sql/sql_parse.cc
--- a/sql/sql_parse.cc	2008-03-27 15:58:39 -03:00
+++ b/sql/sql_parse.cc	2008-03-27 23:18:15 -03:00
@@ -5409,8 +5409,7 @@ bool check_stack_overrun(THD *thd, long 
   {
     sprintf(errbuff[0],ER(ER_STACK_OVERRUN_NEED_MORE),
             stack_used,thread_stack,margin);
-    my_message(ER_STACK_OVERRUN_NEED_MORE,errbuff[0],MYF(0));
-    thd->fatal_error();
+    my_message(ER_STACK_OVERRUN_NEED_MORE,errbuff[0],MYF(ME_FATALERROR));
     return 1;
   }
 #ifndef DBUG_OFF
diff -Nrup a/sql/sql_partition.cc b/sql/sql_partition.cc
--- a/sql/sql_partition.cc	2008-03-27 15:58:39 -03:00
+++ b/sql/sql_partition.cc	2008-03-27 23:18:16 -03:00
@@ -2070,8 +2070,7 @@ char *generate_partition_syntax(partitio
     default:
       DBUG_ASSERT(0);
       /* We really shouldn't get here, no use in continuing from here */
-      my_error(ER_OUT_OF_RESOURCES, MYF(0));
-      current_thd->fatal_error();
+      my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
       DBUG_RETURN(NULL);
   }
   if (part_info->part_expr)
@@ -5049,10 +5048,7 @@ static bool mysql_change_partitions(ALTE
                                          &lpt->deleted, lpt->pack_frm_data,
                                          lpt->pack_frm_len)))
   {
-    if (error != ER_OUTOFMEMORY)
-      file->print_error(error, MYF(0));
-    else
-      lpt->thd->fatal_error();
+    file->print_error(error, MYF(error != ER_OUTOFMEMORY ? 0 : ME_FATALERROR));
     DBUG_RETURN(TRUE);
   }
   DBUG_RETURN(FALSE);
diff -Nrup a/sql/sql_select.cc b/sql/sql_select.cc
--- a/sql/sql_select.cc	2008-03-27 06:56:04 -03:00
+++ b/sql/sql_select.cc	2008-03-27 23:18:16 -03:00
@@ -11340,7 +11340,7 @@ Field *create_tmp_field(THD *thd, TABLE 
     Item_sum *item_sum=(Item_sum*) item;
     result= item_sum->create_tmp_field(group, table, convert_blob_length);
     if (!result)
-      thd->fatal_error();
+      my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
     return result;
   }
   case Item::FIELD_ITEM:
@@ -17322,8 +17322,7 @@ calc_group_buffer(JOIN *join,ORDER *grou
       default:
         /* This case should never be choosen */
         DBUG_ASSERT(0);
-        my_error(ER_OUT_OF_RESOURCES, MYF(0));
-        join->thd->fatal_error();
+        my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
       }
     }
     parts++;
diff -Nrup a/sql/sql_show.cc b/sql/sql_show.cc
--- a/sql/sql_show.cc	2008-03-27 15:58:39 -03:00
+++ b/sql/sql_show.cc	2008-03-27 23:18:16 -03:00
@@ -5158,8 +5158,7 @@ static int get_schema_partitions_record(
       break;
     default:
       DBUG_ASSERT(0);
-      my_error(ER_OUT_OF_RESOURCES, MYF(0));
-      current_thd->fatal_error();
+      my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
       DBUG_RETURN(1);
     }
     table->field[7]->set_notnull();
diff -Nrup a/sql/sql_update.cc b/sql/sql_update.cc
--- a/sql/sql_update.cc	2008-03-27 15:58:39 -03:00
+++ b/sql/sql_update.cc	2008-03-27 23:18:16 -03:00
@@ -653,11 +653,13 @@ int mysql_update(THD *thd,
             If (ignore && error is ignorable) we don't have to
             do anything; otherwise...
           */
+          myf flags= 0;
+
           if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
-            thd->fatal_error(); /* Other handler errors are fatal */
+            flags|= ME_FATALERROR; /* Other handler errors are fatal */
 
           prepare_record_for_error_message(error, table);
-	  table->file->print_error(error,MYF(0));
+	  table->file->print_error(error,MYF(flags));
 	  error= 1;
 	  break;
 	}
@@ -748,9 +750,8 @@ int mysql_update(THD *thd,
     */
   {
     /* purecov: begin inspected */
-    thd->fatal_error();
     prepare_record_for_error_message(loc_error, table);
-    table->file->print_error(loc_error,MYF(0));
+    table->file->print_error(loc_error,MYF(ME_FATALERROR));
     error= 1;
     /* purecov: end */
   }
@@ -1628,11 +1629,13 @@ bool multi_update::send_data(List<Item> 
               If (ignore && error == is ignorable) we don't have to
               do anything; otherwise...
             */
+            myf flags= 0;
+
             if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
-              thd->fatal_error(); /* Other handler errors are fatal */
+              flags|= ME_FATALERROR; /* Other handler errors are fatal */
 
             prepare_record_for_error_message(error, table);
-            table->file->print_error(error,MYF(0));
+            table->file->print_error(error,MYF(flags));
             DBUG_RETURN(1);
           }
         }
@@ -1910,9 +1913,8 @@ int multi_update::do_updates()
 
 err:
   {
-    thd->fatal_error();
     prepare_record_for_error_message(local_error, table);
-    table->file->print_error(local_error,MYF(0));
+    table->file->print_error(local_error,MYF(ME_FATALERROR));
   }
 
 err2:
Thread
bk commit into 6.0 tree (davi:1.2610) BUG#15192Davi Arnaut28 Mar 2008
  • Re: bk commit into 6.0 tree (davi:1.2610) BUG#15192Konstantin Osipov28 Mar 2008