From bfba296d4084eab4b580cddc04e889ad2abdaeb2 Mon Sep 17 00:00:00 2001
From: Jon Olav Hauglid <jon.hauglid@oracle.com>
Date: Thu, 4 Oct 2012 16:15:13 +0200
Subject: Bug#14640599 MEMORY LEAK WHEN EXECUTING STORED ROUTINE EXCEPTION
 HANDLER

When a SP handler is activated, memory is allocated to hold the
MESSAGE_TEXT for the condition that caused the activation.

The problem was that this memory was allocated on the MEM_ROOT belonging
to the stored program. Since this MEM_ROOT is not freed until the
stored program ends, a stored program that causes lots of handler
activations can start using lots of memory. In 5.1 and earlier the
problem did not exist as no MESSAGE_TEXT was allocated if a condition
was raised with a handler present. However, this behavior lead to
a number of other issues such as Bug#23032.

This patch fixes the problem by allocating enough memory for the
necessary MESSAGE_TEXTs in the SP MEM_ROOT when the SP starts and
then re-using this memory each time a handler is activated.

This is the 5.5 version of the patch.
---
 sql/sql_signal.cc | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

(limited to 'sql/sql_signal.cc')

diff --git a/sql/sql_signal.cc b/sql/sql_signal.cc
index 9910dfc924e..e0c2a96ac84 100644
--- a/sql/sql_signal.cc
+++ b/sql/sql_signal.cc
@@ -478,7 +478,7 @@ bool Signal_statement::execute(THD *thd)
 
 bool Resignal_statement::execute(THD *thd)
 {
-  MYSQL_ERROR *signaled;
+  Sql_condition_info *signaled;
   int result= TRUE;
 
   DBUG_ENTER("Resignal_statement::execute");
@@ -491,15 +491,21 @@ bool Resignal_statement::execute(THD *thd)
     DBUG_RETURN(result);
   }
 
+  MYSQL_ERROR signaled_err(thd->mem_root);
+  signaled_err.set(signaled->m_sql_errno,
+                   signaled->m_sql_state,
+                   signaled->m_level,
+                   signaled->m_message);
+
   if (m_cond == NULL)
   {
     /* RESIGNAL without signal_value */
-    result= raise_condition(thd, signaled);
+    result= raise_condition(thd, &signaled_err);
     DBUG_RETURN(result);
   }
 
   /* RESIGNAL with signal_value */
-  result= raise_condition(thd, signaled);
+  result= raise_condition(thd, &signaled_err);
 
   DBUG_RETURN(result);
 }
-- 
cgit v1.2.1