Skip to content

Commit a7bbc77

Browse files
Davi ArnautDavi Arnaut
authored andcommitted
Backport of Bug#15192 to mysql-next-mr
------------------------------------------------------------ revno: 2597.4.17 revision-id: [email protected]/endora.local-20080328174753-24337 parent: sp1r-anozdrin/[email protected] committer: [email protected]/endora.local timestamp: Fri 2008-03-28 14:47:53 -0300 message: 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.
1 parent 5783428 commit a7bbc77

20 files changed

Lines changed: 80 additions & 70 deletions

mysql-test/r/sp-error.result

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1659,6 +1659,17 @@ begin
16591659
declare continue handler for sqlstate '00000' set @x=0;
16601660
end$$
16611661
ERROR 42000: Bad SQLSTATE: '00000'
1662+
drop procedure if exists p1;
1663+
set @old_recursion_depth = @@max_sp_recursion_depth;
1664+
set @@max_sp_recursion_depth = 255;
1665+
create procedure p1(a int)
1666+
begin
1667+
declare continue handler for sqlexception select 'exception';
1668+
call p1(a+1);
1669+
end|
1670+
call p1(1);
1671+
set @@max_sp_recursion_depth = @old_recursion_depth;
1672+
drop procedure p1;
16621673
LOAD DATA INFILE '../../tmp/proc.txt' INTO TABLE mysql.proc;
16631674
CREATE TABLE t1 (a INT, b INT);
16641675
INSERT INTO t1 VALUES (1,1), (2,2);

mysql-test/t/sp-error.test

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2420,6 +2420,27 @@ end$$
24202420
delimiter ;$$
24212421

24222422

2423+
#
2424+
# Bug#15192: "fatal errors" are caught by handlers in stored procedures
2425+
#
2426+
2427+
--disable_warnings
2428+
drop procedure if exists p1;
2429+
--enable_warnings
2430+
set @old_recursion_depth = @@max_sp_recursion_depth;
2431+
set @@max_sp_recursion_depth = 255;
2432+
delimiter |;
2433+
create procedure p1(a int)
2434+
begin
2435+
declare continue handler for sqlexception select 'exception';
2436+
call p1(a+1);
2437+
end|
2438+
delimiter ;|
2439+
--error 0,ER_STACK_OVERRUN_NEED_MORE
2440+
call p1(1);
2441+
set @@max_sp_recursion_depth = @old_recursion_depth;
2442+
drop procedure p1;
2443+
24232444
#
24242445
# BUG#NNNN: New bug synopsis
24252446
#

mysys/my_alloc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
155155
DBUG_ASSERT(alloc_root_inited(mem_root));
156156

157157
length+=ALIGN_SIZE(sizeof(USED_MEM));
158-
if (!(next = (USED_MEM*) my_malloc(length,MYF(MY_WME))))
158+
if (!(next = (USED_MEM*) my_malloc(length,MYF(MY_WME | ME_FATALERROR))))
159159
{
160160
if (mem_root->error_handler)
161161
(*mem_root->error_handler)();
@@ -198,7 +198,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
198198
get_size= length+ALIGN_SIZE(sizeof(USED_MEM));
199199
get_size= max(get_size, block_size);
200200

201-
if (!(next = (USED_MEM*) my_malloc(get_size,MYF(MY_WME))))
201+
if (!(next = (USED_MEM*) my_malloc(get_size,MYF(MY_WME | ME_FATALERROR))))
202202
{
203203
if (mem_root->error_handler)
204204
(*mem_root->error_handler)();

sql/event_data_objects.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ Event_basic::Event_basic()
196196
{
197197
DBUG_ENTER("Event_basic::Event_basic");
198198
/* init memory root */
199-
init_alloc_root(&mem_root, 256, 512);
199+
init_sql_alloc(&mem_root, 256, 512);
200200
dbname.str= name.str= NULL;
201201
dbname.length= name.length= 0;
202202
time_zone= NULL;

sql/ha_partition.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,8 +1980,7 @@ partition_element *ha_partition::find_partition_element(uint part_id)
19801980
return part_elem;
19811981
}
19821982
DBUG_ASSERT(0);
1983-
my_error(ER_OUT_OF_RESOURCES, MYF(0));
1984-
current_thd->fatal_error(); // Abort
1983+
my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
19851984
return NULL;
19861985
}
19871986

sql/item_func.cc

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3818,7 +3818,7 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
38183818
uint size=ALIGN_SIZE(sizeof(user_var_entry))+name.length+1+extra_size;
38193819
if (!my_hash_inited(hash))
38203820
return 0;
3821-
if (!(entry = (user_var_entry*) my_malloc(size,MYF(MY_WME))))
3821+
if (!(entry = (user_var_entry*) my_malloc(size,MYF(MY_WME | ME_FATALERROR))))
38223822
return 0;
38233823
entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+
38243824
extra_size;
@@ -3956,6 +3956,8 @@ bool Item_func_set_user_var::register_field_in_read_map(uchar *arg)
39563956
@param dv derivation for new value
39573957
@param unsigned_arg indiates if a value of type INT_RESULT is unsigned
39583958
3959+
@note Sets error and fatal error if allocation fails.
3960+
39593961
@retval
39603962
false success
39613963
@retval
@@ -3999,7 +4001,8 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length,
39994001
if (entry->value == pos)
40004002
entry->value=0;
40014003
entry->value= (char*) my_realloc(entry->value, length,
4002-
MYF(MY_ALLOW_ZERO_PTR | MY_WME));
4004+
MYF(MY_ALLOW_ZERO_PTR | MY_WME |
4005+
ME_FATALERROR));
40034006
if (!entry->value)
40044007
return 1;
40054008
}
@@ -4036,7 +4039,6 @@ Item_func_set_user_var::update_hash(void *ptr, uint length,
40364039
if (::update_hash(entry, (null_value= args[0]->null_value),
40374040
ptr, length, res_type, cs, dv, unsigned_arg))
40384041
{
4039-
current_thd->fatal_error(); // Probably end of memory
40404042
null_value= 1;
40414043
return 1;
40424044
}
@@ -4769,11 +4771,6 @@ void Item_func_get_user_var::fix_length_and_dec()
47694771
m_cached_result_type= STRING_RESULT;
47704772
max_length= MAX_BLOB_WIDTH;
47714773
}
4772-
4773-
if (error)
4774-
thd->fatal_error();
4775-
4776-
return;
47774774
}
47784775

47794776

@@ -4857,18 +4854,16 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
48574854

48584855
void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs)
48594856
{
4860-
if (::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs,
4861-
DERIVATION_IMPLICIT, 0 /* unsigned_arg */))
4862-
current_thd->fatal_error(); // Probably end of memory
4857+
::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs,
4858+
DERIVATION_IMPLICIT, 0 /* unsigned_arg */);
48634859
}
48644860

48654861

48664862
void Item_user_var_as_out_param::set_value(const char *str, uint length,
48674863
CHARSET_INFO* cs)
48684864
{
4869-
if (::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
4870-
DERIVATION_IMPLICIT, 0 /* unsigned_arg */))
4871-
current_thd->fatal_error(); // Probably end of memory
4865+
::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
4866+
DERIVATION_IMPLICIT, 0 /* unsigned_arg */);
48724867
}
48734868

48744869

sql/item_subselect.cc

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1735,8 +1735,6 @@ subselect_union_engine::subselect_union_engine(st_select_lex_unit *u,
17351735
:subselect_engine(item_arg, result_arg)
17361736
{
17371737
unit= u;
1738-
if (!result_arg) //out of memory
1739-
current_thd->fatal_error();
17401738
unit->item= item_arg;
17411739
}
17421740

@@ -1748,10 +1746,7 @@ int subselect_single_select_engine::prepare()
17481746
join= new JOIN(thd, select_lex->item_list,
17491747
select_lex->options | SELECT_NO_UNLOCK, result);
17501748
if (!join || !result)
1751-
{
1752-
thd->fatal_error(); //out of memory
1753-
return 1;
1754-
}
1749+
return 1; /* Fatal error is set already. */
17551750
prepared= 1;
17561751
SELECT_LEX *save_select= thd->lex->current_select;
17571752
thd->lex->current_select= select_lex;

sql/opt_sum.cc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
175175
error= tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
176176
if(error)
177177
{
178-
tl->table->file->print_error(error, MYF(0));
179-
tl->table->in_use->fatal_error();
178+
tl->table->file->print_error(error, MYF(ME_FATALERROR));
180179
return error;
181180
}
182181
count*= tl->table->file->stats.records;
@@ -427,8 +426,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
427426
if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
428427
return HA_ERR_KEY_NOT_FOUND; // No rows matching WHERE
429428
/* HA_ERR_LOCK_DEADLOCK or some other error */
430-
table->file->print_error(error, MYF(0));
431-
table->in_use->fatal_error();
429+
table->file->print_error(error, MYF(ME_FATALERROR));
432430
return(error);
433431
}
434432
removed_tables|= table->map;

sql/sp_head.cc

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4012,10 +4012,7 @@ sp_add_to_query_tables(THD *thd, LEX *lex,
40124012
TABLE_LIST *table;
40134013

40144014
if (!(table= (TABLE_LIST *)thd->calloc(sizeof(TABLE_LIST))))
4015-
{
4016-
thd->fatal_error();
40174015
return NULL;
4018-
}
40194016
table->db_length= strlen(db);
40204017
table->db= thd->strmake(db, table->db_length);
40214018
table->table_name_length= strlen(name);

sql/sql_class.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1978,6 +1978,7 @@ class THD :public Statement,
19781978
*/
19791979
inline void fatal_error()
19801980
{
1981+
DBUG_ASSERT(main_da.is_error());
19811982
is_fatal_error= 1;
19821983
DBUG_PRINT("error",("Fatal error set"));
19831984
}
@@ -2139,7 +2140,10 @@ class THD :public Statement,
21392140
else
21402141
{
21412142
x_free(db);
2142-
db= new_db ? my_strndup(new_db, new_db_len, MYF(MY_WME)) : NULL;
2143+
if (new_db)
2144+
db= my_strndup(new_db, new_db_len, MYF(MY_WME | ME_FATALERROR));
2145+
else
2146+
db= NULL;
21432147
}
21442148
db_length= db ? new_db_len : 0;
21452149
return new_db && !db;

0 commit comments

Comments
 (0)