diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 82dda16933f3c5e638863519d3995dbfd1b03dd3..f9e6eae7e577718a54ca2f57a29db58cf17741b9 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -3360,4 +3360,34 @@ call bug12979_2()|
 internal_var
 NULL
 drop procedure bug12979_2|
+drop table if exists t3|
+drop procedure if exists bug6127|
+create table t3 (s1 int unique)|
+set @sm=@@sql_mode|
+set sql_mode='traditional'|
+create procedure bug6127()
+begin
+declare continue handler for sqlstate '23000'
+    begin
+declare continue handler for sqlstate '22003'
+        insert into t3 values (0);
+insert into t3 values (1000000000000000);
+end;
+insert into t3 values (1);
+insert into t3 values (1);
+end|
+call bug6127()|
+select * from t3|
+s1
+0
+1
+call bug6127()|
+ERROR 23000: Duplicate entry '0' for key 1
+select * from t3|
+s1
+0
+1
+set sql_mode=@sm|
+drop table t3|
+drop procedure bug6127|
 drop table t1,t2;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index afcbd98277a7f6017750d23c9d7a185524214038..65d4f89e2bb4fea9aba88faa1dc5a70167a3f4ed 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -4228,6 +4228,42 @@ call bug12979_2()|
 drop procedure bug12979_2|
 
 
+#
+# BUG#6127: Stored procedure handlers within handlers don't work
+#
+--disable_warnings
+drop table if exists t3|
+drop procedure if exists bug6127|
+--enable_warnings
+create table t3 (s1 int unique)|
+
+set @sm=@@sql_mode|
+set sql_mode='traditional'|
+
+create procedure bug6127()
+begin
+  declare continue handler for sqlstate '23000'
+    begin
+      declare continue handler for sqlstate '22003'
+        insert into t3 values (0);
+
+      insert into t3 values (1000000000000000);
+    end;
+
+  insert into t3 values (1);
+  insert into t3 values (1);
+end|
+
+call bug6127()|
+select * from t3|
+--error ER_DUP_ENTRY
+call bug6127()|
+select * from t3|
+set sql_mode=@sm|
+drop table t3|
+drop procedure bug6127|
+
+
 #
 # BUG#NNNN: New bug synopsis
 #
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 36a37924ea45c408e0e1cd6742865ff98a0b4d44..671acbc2a0cade34c908b3f903f6b1c84f897d22 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1015,7 +1015,7 @@ int sp_head::execute(THD *thd)
 	ip= hip;
 	ret= 0;
 	ctx->clear_handler();
-	ctx->in_handler= TRUE;
+	ctx->enter_handler(hip);
         thd->clear_error();
 	thd->killed= THD::NOT_KILLED;
 	continue;
@@ -2378,7 +2378,7 @@ sp_instr_hreturn::execute(THD *thd, uint *nextp)
     thd->spcont->restore_variables(m_frame);
     *nextp= thd->spcont->pop_hstack();
   }
-  thd->spcont->in_handler= FALSE;
+  thd->spcont->exit_handler();
   DBUG_RETURN(0);
 }
 
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index fcb7719aeb131adb5823edd8ce64de21d3f301aa..252bd7e5cab4e1b7b0b4f2a893d5c6e331c099b9 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -31,12 +31,12 @@
 
 sp_rcontext::sp_rcontext(uint fsize, uint hmax, uint cmax)
   : m_count(0), m_fsize(fsize), m_result(NULL), m_hcount(0), m_hsp(0),
-    m_hfound(-1), m_ccount(0)
+    m_ihsp(0), m_hfound(-1), m_ccount(0)
 {
-  in_handler= FALSE;
   m_frame= (Item **)sql_alloc(fsize * sizeof(Item*));
   m_handler= (sp_handler_t *)sql_alloc(hmax * sizeof(sp_handler_t));
   m_hstack= (uint *)sql_alloc(hmax * sizeof(uint));
+  m_in_handler= (uint *)sql_alloc(hmax * sizeof(uint));
   m_cstack= (sp_cursor **)sql_alloc(cmax * sizeof(sp_cursor *));
   m_saved.empty();
 }
@@ -68,8 +68,6 @@ bool
 sp_rcontext::find_handler(uint sql_errno,
                           MYSQL_ERROR::enum_warning_level level)
 {
-  if (in_handler)
-    return 0;			// Already executing a handler
   if (m_hfound >= 0)
     return 1;			// Already got one
 
@@ -79,6 +77,13 @@ sp_rcontext::find_handler(uint sql_errno,
   while (i--)
   {
     sp_cond_type_t *cond= m_handler[i].cond;
+    int j= m_ihsp;
+
+    while (j--)
+      if (m_in_handler[j] == m_handler[i].handler)
+	break;
+    if (j >= 0)
+      continue;                 // Already executing this handler
 
     switch (cond->type)
     {
diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h
index 9c0fa88fe3461eb1704f652ef1728e32df1f2876..22fa4f6e86596a494e7f16314510202a76c798e2 100644
--- a/sql/sp_rcontext.h
+++ b/sql/sp_rcontext.h
@@ -58,7 +58,6 @@ class sp_rcontext : public Sql_alloc
 
  public:
 
-  bool in_handler;
   /*
     Arena used to (re) allocate items on . E.g. reallocate INOUT/OUT
     SP parameters when they don't fit into prealloced items. This
@@ -169,6 +168,18 @@ class sp_rcontext : public Sql_alloc
     return m_hstack[--m_hsp];
   }
 
+  inline void
+  enter_handler(int hid)
+  {
+    m_in_handler[m_ihsp++]= hid;
+  }
+
+  inline void
+  exit_handler()
+  {
+    m_ihsp-= 1;
+  }
+
   // Save variables starting at fp and up
   void
   save_variables(uint fp);
@@ -203,12 +214,14 @@ class sp_rcontext : public Sql_alloc
 
   Item *m_result;		// For FUNCTIONs
 
-  sp_handler_t *m_handler;
-  uint m_hcount;
-  uint *m_hstack;
-  uint m_hsp;
-  int m_hfound;			// Set by find_handler; -1 if not found
-  List<Item> m_saved;		// Saved variables
+  sp_handler_t *m_handler;      // Visible handlers
+  uint m_hcount;                // Stack pointer for m_handler
+  uint *m_hstack;               // Return stack for continue handlers
+  uint m_hsp;                   // Stack pointer for m_hstack
+  uint *m_in_handler;           // Active handler, for recursion check
+  uint m_ihsp;                  // Stack pointer for m_in_handler
+  int m_hfound;                 // Set by find_handler; -1 if not found
+  List<Item> m_saved;           // Saved variables during handler exec.
 
   sp_cursor **m_cstack;
   uint m_ccount;