List:Internals« Previous MessageNext Message »
From:pem Date:June 3 2005 5:46pm
Subject:bk commit into 5.0 tree (pem:1.1911) BUG#10968
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of pem. When pem 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
  1.1911 05/06/03 19:21:12 pem@stripped +1 -0
  Fixed BUG#10968: Stored procedures: crash if long loop
    Free memory after all SP invokation.

  sql/sp_head.cc
    1.142 05/06/03 19:21:06 pem@stripped +71 -4
    Fixed memory leaks in SP invokation. Have to release memory after each call,
    or items and contexts are not released until it's too late.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	pem
# Host:	mysql.comhem.se
# Root:	/home/pem/work/mysql-5.0

--- 1.141/sql/sp_head.cc	Wed Jun  1 12:17:38 2005
+++ 1.142/sql/sp_head.cc	Fri Jun  3 19:21:06 2005
@@ -696,6 +696,8 @@
   sp_rcontext *nctx = NULL;
   uint i;
   int ret;
+  MEM_ROOT *old_mem_root, call_mem_root;
+  Item *old_free_list, *call_free_list;
 
   if (argcount != params)
   {
@@ -706,6 +708,12 @@
     DBUG_RETURN(-1);
   }
 
+  init_alloc_root(&call_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
+  old_mem_root= thd->mem_root;
+  thd->mem_root= &call_mem_root;
+  old_free_list= thd->free_list; // Keep the old list
+  thd->free_list= NULL;	// Start a new one
+
   // QQ Should have some error checking here? (types, etc...)
   nctx= new sp_rcontext(csize, hmax, cmax);
   for (i= 0 ; i < params && i < argcount ; i++)
@@ -736,13 +744,20 @@
 
   ret= execute(thd);
 
+  // Partially restore context now.
+  // We still need the call mem root and free list for processing
+  // of the result.
+  call_free_list= thd->free_list;
+  thd->free_list= old_free_list;
+  thd->mem_root= old_mem_root;
+
   if (m_type == TYPE_ENUM_FUNCTION && ret == 0)
   {
     /* We need result only in function but not in trigger */
     Item *it= nctx->get_result();
 
     if (it)
-      *resp= it;
+      *resp= sp_eval_func_item(thd, &it, m_returns, NULL);
     else
     {
       my_error(ER_SP_NORETURNEND, MYF(0), m_name.str);
@@ -752,6 +767,12 @@
 
   nctx->pop_all_cursors();	// To avoid memory leaks after an error
   thd->spcont= octx;
+
+  // Now get rid of the rest of the callee context
+  cleanup_items(call_free_list);
+  free_items(call_free_list);
+  free_root(&call_mem_root, MYF(0));
+
   DBUG_RETURN(ret);
 }
 
@@ -781,6 +802,8 @@
   sp_rcontext *octx = thd->spcont;
   sp_rcontext *nctx = NULL;
   my_bool tmp_octx = FALSE;	// True if we have allocated a temporary octx
+  MEM_ROOT *old_mem_root, call_mem_root;
+  Item *old_free_list, *call_free_list;
 
   if (args->elements != params)
   {
@@ -789,6 +812,12 @@
     DBUG_RETURN(-1);
   }
 
+  init_alloc_root(&call_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
+  old_mem_root= thd->mem_root;
+  thd->mem_root= &call_mem_root;
+  old_free_list= thd->free_list; // Keep the old list
+  thd->free_list= NULL;	// Start a new one
+
   if (csize > 0 || hmax > 0 || cmax > 0)
   {
     Item_null *nit= NULL;	// Re-use this, and only create if needed
@@ -854,9 +883,16 @@
   if (! ret)
     ret= execute(thd);
 
+  // Partially restore context now.
+  // We still need the call mem root and free list for processing
+  // of out parameters.
+  call_free_list= thd->free_list;
+  thd->free_list= old_free_list;
+  thd->mem_root= old_mem_root;
+
   if (!ret && csize > 0)
   {
-    List_iterator_fast<Item> li(*args);
+    List_iterator<Item> li(*args);
     Item *it;
 
     // Copy back all OUT or INOUT values to the previous frame, or
@@ -868,8 +904,34 @@
       if (pvar->mode != sp_param_in)
       {
 	if (it->is_splocal())
-	  octx->set_item(static_cast<Item_splocal *>(it)->get_offset(),
-			 nctx->get_item(i));
+	{
+	  // Have to copy the item to the caller's mem_root
+	  Item *copy;
+	  uint offset= static_cast<Item_splocal *>(it)->get_offset();
+	  Item *val= nctx->get_item(i);
+	  Item *orig= octx->get_item(offset);
+	  Item *o_item_next;
+	  Item *o_free_list= thd->free_list;
+	  LINT_INIT(o_item_next);
+
+	  if (orig)
+	    o_item_next= orig->next;
+	  copy= sp_eval_func_item(thd, &val, pvar->type, orig); // Copy
+	  if (!copy)
+	  {
+	    ret= -1;
+	    break;
+	  }
+	  if (copy != orig)
+	    octx->set_item(offset, copy);
+	  if (orig && copy == orig)
+	  {
+	    // A reused item slot, where the constructor put it in the
+	    // free_list, so we have to restore the list.
+	    thd->free_list= o_free_list;
+	    copy->next= o_item_next;
+	  }
+	}
 	else
 	{
 	  Item_func_get_user_var *guv= item_is_user_var(it);
@@ -899,6 +961,11 @@
   if (nctx)
     nctx->pop_all_cursors();	// To avoid memory leaks after an error
   thd->spcont= octx;
+
+  // Now get rid of the rest of the callee context
+  cleanup_items(call_free_list);
+  free_items(call_free_list);
+  free_root(&call_mem_root, MYF(0));
 
   DBUG_RETURN(ret);
 }
Thread
bk commit into 5.0 tree (pem:1.1911) BUG#10968pem3 Jun