Skip to content

Commit 62e8f25

Browse files
author
Nisha Gopalakrishnan
committed
Bug#11757464:SERVER CRASH IN RECURSIVE CALL WHEN OOM
Analysis: --------- When the server is out of memory, an error is raised to indicate the same. Handling the error requires more memory to be allocated which fails, hence the error handling loops in a recursion and causes the server to crash. Fix: --- a) Prevents pushing the 'out of memory' error condition to the diagnostic area as it requires memory allocation. GET DIAGNOSTICS, SHOW WARNINGS and SHOW ERRORS statements will not show information about this error. However the 'out of memory' error is returned to the client. b) It sets the ME_FATALERROR flag when 'out of memory' errors are reported (for places where the flag is not already set). This flag prevents activation of SP error handlers which also require memory allocation and therefore are likely to fail.
1 parent a440844 commit 62e8f25

12 files changed

+39
-20
lines changed

mysys/mf_keycache.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,8 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
444444
if (blocks < 8)
445445
{
446446
my_errno= ENOMEM;
447-
my_error(EE_OUTOFMEMORY, MYF(0), blocks * keycache->key_cache_block_size);
447+
my_error(EE_OUTOFMEMORY, MYF(ME_FATALERROR),
448+
blocks * keycache->key_cache_block_size);
448449
goto err;
449450
}
450451
blocks= blocks / 4*3;

mysys/my_lockmem.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ uchar *my_malloc_lock(uint size,myf MyFlags)
4343
if (!(ptr=memalign(pagesize,size)))
4444
{
4545
if (MyFlags & (MY_FAE+MY_WME))
46-
my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),size);
46+
my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG+ME_FATALERROR), size);
4747
DBUG_RETURN(0);
4848
}
4949
success = mlock((uchar*) ptr,size);

mysys/my_malloc.c

+9-3
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,20 @@ void *my_malloc(size_t size, myf my_flags)
4141
free(point);
4242
point= NULL;
4343
});
44+
DBUG_EXECUTE_IF("simulate_persistent_out_of_memory",
45+
{
46+
free(point);
47+
point= NULL;
48+
});
4449

4550
if (point == NULL)
4651
{
4752
my_errno=errno;
4853
if (my_flags & MY_FAE)
4954
error_handler_hook=fatal_error_handler_hook;
5055
if (my_flags & (MY_FAE+MY_WME))
51-
my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG+ME_NOREFRESH),size);
56+
my_error(EE_OUTOFMEMORY, MYF(ME_BELL + ME_WAITTANG +
57+
ME_NOREFRESH + ME_FATALERROR),size);
5258
DBUG_EXECUTE_IF("simulate_out_of_memory",
5359
DBUG_SET("-d,simulate_out_of_memory"););
5460
if (my_flags & MY_FAE)
@@ -90,7 +96,7 @@ void *my_realloc(void *oldpoint, size_t size, myf my_flags)
9096
DBUG_RETURN(oldpoint);
9197
my_errno=errno;
9298
if (my_flags & MY_FAE+MY_WME)
93-
my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),size);
99+
my_error(EE_OUTOFMEMORY, MYF(ME_BELL + ME_WAITTANG + ME_FATALERROR),size);
94100
}
95101
else
96102
{
@@ -106,7 +112,7 @@ void *my_realloc(void *oldpoint, size_t size, myf my_flags)
106112
DBUG_RETURN(oldpoint);
107113
my_errno=errno;
108114
if (my_flags & (MY_FAE+MY_WME))
109-
my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG), size);
115+
my_error(EE_OUTOFMEMORY, MYF(ME_BELL + ME_WAITTANG + ME_FATALERROR), size);
110116
}
111117
#endif
112118
DBUG_PRINT("exit",("ptr: %p", point));

mysys/my_once.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ void* my_once_alloc(size_t Size, myf MyFlags)
5959
{
6060
my_errno=errno;
6161
if (MyFlags & (MY_FAE+MY_WME))
62-
my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),get_size);
62+
my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG+ME_FATALERROR), get_size);
6363
return((uchar*) 0);
6464
}
6565
DBUG_PRINT("test",("my_once_malloc %lu byte malloced", (ulong) get_size));

sql/handler.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,8 @@ handler *get_ha_partition(partition_info *part_info)
356356
}
357357
else
358358
{
359-
my_error(ER_OUTOFMEMORY, MYF(0), static_cast<int>(sizeof(ha_partition)));
359+
my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR),
360+
static_cast<int>(sizeof(ha_partition)));
360361
}
361362
DBUG_RETURN(((handler*) partition));
362363
}

sql/item_sum.cc

+4
Original file line numberDiff line numberDiff line change
@@ -3211,8 +3211,12 @@ bool Item_func_group_concat::add()
32113211
TREE_ELEMENT *el= 0; // Only for safety
32123212
if (row_eligible && tree)
32133213
{
3214+
DBUG_EXECUTE_IF("trigger_OOM_in_gconcat_add",
3215+
DBUG_SET("+d,simulate_persistent_out_of_memory"););
32143216
el= tree_insert(tree, table->record[0] + table->s->null_bytes, 0,
32153217
tree->custom_arg);
3218+
DBUG_EXECUTE_IF("trigger_OOM_in_gconcat_add",
3219+
DBUG_SET("-d,simulate_persistent_out_of_memory"););
32163220
/* check if there was enough memory to insert the row */
32173221
if (!el)
32183222
return 1;

sql/sql_binlog.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ void mysql_client_binlog_statement(THD* thd)
107107
rli->relay_log.description_event_for_exec &&
108108
buf))
109109
{
110-
my_error(ER_OUTOFMEMORY, MYF(0), 1); /* needed 1 bytes */
110+
my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), 1); /* needed 1 bytes */
111111
goto end;
112112
}
113113

sql/sql_class.cc

+10-6
Original file line numberDiff line numberDiff line change
@@ -1136,10 +1136,14 @@ MYSQL_ERROR* THD::raise_condition(uint sql_errno,
11361136

11371137
query_cache_abort(&query_cache_tls);
11381138

1139-
/* When simulating OOM, skip writing to error log to avoid mtr errors */
1140-
DBUG_EXECUTE_IF("simulate_out_of_memory", DBUG_RETURN(NULL););
1141-
1142-
cond= warning_info->push_warning(this, sql_errno, sqlstate, level, msg);
1139+
/*
1140+
Avoid pushing a condition for out of memory errors as this will require
1141+
memory allocation and therefore might fail.
1142+
*/
1143+
if (sql_errno != EE_OUTOFMEMORY && sql_errno != ER_OUTOFMEMORY)
1144+
{
1145+
cond= warning_info->push_warning(this, sql_errno, sqlstate, level, msg);
1146+
}
11431147
DBUG_RETURN(cond);
11441148
}
11451149

@@ -1938,7 +1942,7 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, long key_length)
19381942
key_length + 1);
19391943
if (!new_table)
19401944
{
1941-
my_error(EE_OUTOFMEMORY, MYF(ME_BELL),
1945+
my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_FATALERROR),
19421946
ALIGN_SIZE(sizeof(TABLE_LIST)) + key_length + 1);
19431947
killed= KILL_CONNECTION;
19441948
return 0;
@@ -2493,7 +2497,7 @@ bool select_export::send_data(List<Item> &items)
24932497
set_if_smaller(estimated_bytes, UINT_MAX32);
24942498
if (cvt_str.realloc((uint32) estimated_bytes))
24952499
{
2496-
my_error(ER_OUTOFMEMORY, MYF(0), (uint32) estimated_bytes);
2500+
my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), (uint32) estimated_bytes);
24972501
goto err;
24982502
}
24992503

sql/sql_partition.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -7044,7 +7044,8 @@ void set_key_field_ptr(KEY *key_info, const uchar *new_buf,
70447044

70457045
void mem_alloc_error(size_t size)
70467046
{
7047-
my_error(ER_OUTOFMEMORY, MYF(0), static_cast<int>(size));
7047+
my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR),
7048+
static_cast<int>(size));
70487049
}
70497050

70507051
#ifdef WITH_PARTITION_STORAGE_ENGINE

sql/sql_prepare.cc

+4-3
Original file line numberDiff line numberDiff line change
@@ -1475,7 +1475,8 @@ static int mysql_test_select(Prepared_statement *stmt,
14751475

14761476
if (!lex->result && !(lex->result= new (stmt->mem_root) select_send))
14771477
{
1478-
my_error(ER_OUTOFMEMORY, MYF(0), static_cast<int>(sizeof(select_send)));
1478+
my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR),
1479+
static_cast<int>(sizeof(select_send)));
14791480
goto error;
14801481
}
14811482

@@ -1842,7 +1843,7 @@ static bool mysql_test_multidelete(Prepared_statement *stmt,
18421843
stmt->thd->lex->current_select= &stmt->thd->lex->select_lex;
18431844
if (add_item_to_list(stmt->thd, new Item_null()))
18441845
{
1845-
my_error(ER_OUTOFMEMORY, MYF(0), 0);
1846+
my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), 0);
18461847
goto error;
18471848
}
18481849

@@ -3755,7 +3756,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
37553756
alloc_query(thd, (char*) expanded_query->ptr(),
37563757
expanded_query->length()))
37573758
{
3758-
my_error(ER_OUTOFMEMORY, 0, expanded_query->length());
3759+
my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), expanded_query->length());
37593760
goto error;
37603761
}
37613762
/*

sql/sql_select.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -14417,7 +14417,7 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
1441714417
}
1441814418
if (copy_blobs(first_field))
1441914419
{
14420-
my_message(ER_OUTOFMEMORY, ER(ER_OUTOFMEMORY), MYF(0));
14420+
my_message(ER_OUTOFMEMORY, ER(ER_OUTOFMEMORY), MYF(ME_FATALERROR));
1442114421
error=0;
1442214422
goto err;
1442314423
}

storage/myisam/myisampack.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -2151,7 +2151,8 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees)
21512151
*/
21522152
if (!(packed_tree=(uint*) my_alloca(sizeof(uint)*length*2)))
21532153
{
2154-
my_error(EE_OUTOFMEMORY,MYF(ME_BELL),sizeof(uint)*length*2);
2154+
my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_FATALERROR),
2155+
sizeof(uint)*length*2);
21552156
return 0;
21562157
}
21572158

0 commit comments

Comments
 (0)