23
23
#include " sql_tmp_table.h" // create_virtual_tmp_table
24
24
#include " sp_instr.h"
25
25
26
+ extern " C" void sql_alloc_error_handler (void );
26
27
27
28
// /////////////////////////////////////////////////////////////////////////
28
29
// sp_rcontext implementation.
@@ -51,8 +52,12 @@ sp_rcontext::~sp_rcontext()
51
52
while (m_activated_handlers.elements ())
52
53
delete m_activated_handlers.pop ();
53
54
54
- // Leave m_visible_handlers, m_var_items, m_cstack
55
- // and m_case_expr_holders untouched.
55
+ while (m_visible_handlers.elements ())
56
+ delete m_visible_handlers.pop ();
57
+
58
+ pop_all_cursors ();
59
+
60
+ // Leave m_var_items and m_case_expr_holders untouched.
56
61
// They are allocated in mem roots and will be freed accordingly.
57
62
}
58
63
@@ -158,13 +163,19 @@ bool sp_rcontext::set_return_value(THD *thd, Item **return_value_item)
158
163
bool sp_rcontext::push_cursor (sp_instr_cpush *i)
159
164
{
160
165
/*
161
- We should create cursors in the callers arena, as
162
- it could be (and usually is) used in several instructions.
166
+ We should create cursors on the system heap because:
167
+ - they could be (and usually are) used in several instructions,
168
+ thus they can not be stored on an execution mem-root;
169
+ - a cursor can be pushed/popped many times in a loop, having these objects
170
+ on callers' mem-root would lead to a memory leak in every iteration.
163
171
*/
164
- sp_cursor *c= new (callers_arena-> mem_root ) sp_cursor (i);
172
+ sp_cursor *c= new (std::nothrow ) sp_cursor (i);
165
173
166
- if (c == NULL )
174
+ if (!c)
175
+ {
176
+ sql_alloc_error_handler ();
167
177
return true ;
178
+ }
168
179
169
180
m_cstack[m_ccount++]= c;
170
181
return false ;
@@ -183,14 +194,21 @@ void sp_rcontext::pop_cursors(uint count)
183
194
bool sp_rcontext::push_handler (sp_handler *handler, uint first_ip)
184
195
{
185
196
/*
186
- We should create handler entries in the callers arena, as
187
- they could be (and usually are) used in several instructions.
197
+ We should create handler entries on the system heap because:
198
+ - they could be (and usually are) used in several instructions,
199
+ thus they can not be stored on an execution mem-root;
200
+ - a handler can be pushed/popped many times in a loop, having these
201
+ objects on callers' mem-root would lead to a memory leak in every
202
+ iteration.
188
203
*/
189
204
sp_handler_entry *he=
190
- new (callers_arena-> mem_root ) sp_handler_entry (handler, first_ip);
205
+ new (std::nothrow ) sp_handler_entry (handler, first_ip);
191
206
192
- if (he == NULL )
207
+ if (!he)
208
+ {
209
+ sql_alloc_error_handler ();
193
210
return true ;
211
+ }
194
212
195
213
return m_visible_handlers.append (he);
196
214
}
@@ -203,7 +221,7 @@ void sp_rcontext::pop_handlers(sp_pcontext *current_scope)
203
221
int handler_level= m_visible_handlers.at (i)->handler ->scope ->get_level ();
204
222
205
223
if (handler_level >= current_scope->get_level ())
206
- m_visible_handlers.pop ();
224
+ delete m_visible_handlers.pop ();
207
225
}
208
226
}
209
227
@@ -390,9 +408,16 @@ bool sp_rcontext::handle_sql_condition(THD *thd,
390
408
cur_spi->get_cont_dest () : 0 ;
391
409
392
410
/* Add a frame to handler-call-stack. */
393
- Handler_call_frame *frame= new Handler_call_frame (found_handler,
394
- found_condition,
395
- continue_ip);
411
+ Handler_call_frame *frame=
412
+ new (std::nothrow) Handler_call_frame (found_handler,
413
+ found_condition,
414
+ continue_ip);
415
+ if (!frame)
416
+ {
417
+ sql_alloc_error_handler ();
418
+ DBUG_RETURN (false );
419
+ }
420
+
396
421
m_activated_handlers.append (frame);
397
422
398
423
/* End aborted result set. */
0 commit comments