=== modified file 'libmysql/libmysql.c'
--- libmysql/libmysql.c	2013-01-29 14:10:47 +0000
+++ libmysql/libmysql.c	2013-05-31 17:19:18 +0000
@@ -1273,6 +1273,7 @@
 #define RESET_LONG_DATA 2
 #define RESET_STORE_RESULT 4
 #define RESET_CLEAR_ERROR 8
+#define RESET_ALL_BUFFERS 16
 
 static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags);
 
@@ -4606,6 +4607,14 @@
             *mysql->unbuffered_fetch_owner= TRUE;
           mysql->status= MYSQL_STATUS_READY;
         }
+        if (flags & RESET_ALL_BUFFERS)
+        {
+          /* mysql_stmt_next_result will flush all pending
+             result sets 
+          */
+          while (mysql_more_results(mysql) &&
+                 mysql_stmt_next_result(stmt) == 0);
+        }
       }
       if (flags & RESET_SERVER_SIDE)
       {
@@ -4670,27 +4679,18 @@
   {
     mysql->stmts= list_delete(mysql->stmts, &stmt->list);
     /*
-      Clear NET error state: if the following commands come through
-      successfully, connection will still be usable for other commands.
+     Clear NET error state: if the following commands come through
+     successfully, connection will still be usable for other commands.
     */
     net_clear_error(&mysql->net);
+
     if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
     {
       uchar buff[MYSQL_STMT_HEADER];             /* 4 bytes - stmt id */
 
-      if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
-        mysql->unbuffered_fetch_owner= 0;
-      if (mysql->status != MYSQL_STATUS_READY)
-      {
-        /*
-          Flush result set of the connection. If it does not belong
-          to this statement, set a warning.
-        */
-        (*mysql->methods->flush_use_result)(mysql, TRUE);
-        if (mysql->unbuffered_fetch_owner)
-          *mysql->unbuffered_fetch_owner= TRUE;
-        mysql->status= MYSQL_STATUS_READY;
-      }
+      if ((rc= reset_stmt_handle(stmt, RESET_ALL_BUFFERS | RESET_CLEAR_ERROR)))
+        return rc;
+
       int4store(buff, stmt->stmt_id);
       if ((rc= stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt)))
       {
@@ -4722,7 +4722,7 @@
   /* Reset the client and server sides of the prepared statement */
   DBUG_RETURN(reset_stmt_handle(stmt,
                                 RESET_SERVER_SIDE | RESET_LONG_DATA |
-                                RESET_CLEAR_ERROR));
+                                RESET_ALL_BUFFERS | RESET_CLEAR_ERROR));
 }
 
 /*
@@ -4834,7 +4834,6 @@
   DBUG_RETURN(-1);				/* No more results */
 }
 
-
 int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt)
 {
   MYSQL *mysql= stmt->mysql;

=== modified file 'tests/mysql_client_test.c'
--- tests/mysql_client_test.c	2013-04-15 13:09:22 +0000
+++ tests/mysql_client_test.c	2013-05-31 17:06:24 +0000
@@ -18850,6 +18850,109 @@
   myquery(rc);
 }
 
+/* 
+   mdev_4603: mysql_stmt_reset doesn't clear
+              all result sets (from stored procedures).
+   This test requires also fix for bug 4604
+*/
+static void test_mdev_4603()
+{
+  MYSQL *my;
+  MYSQL_STMT *stmt;
+  int i, rc;
+  int a[] = {10,20,30};
+  MYSQL_BIND bind[3];
+
+  myheader("test_mdev_4603");
+  my= mysql_client_init(NULL);
+
+  if (!mysql_real_connect(my, opt_host, opt_user,
+                               opt_password, current_db, opt_port,
+                               opt_unix_socket, CLIENT_MULTI_RESULTS))
+    DIE("mysql_real_connect failed");
+
+  /* 1st test:
+     use a procedure with out param
+  */
+  rc= mysql_query(my, "DROP PROCEDURE IF EXISTS p1");
+  myquery(rc);
+
+  rc= mysql_query(mysql, "CREATE PROCEDURE p1(OUT p_out VARCHAR(19), IN p_in INT, INOUT p_inout INT)" 
+                         "BEGIN "
+                          "  SET p_in = 300, p_out := 'This is OUT param', p_inout = 200; "
+                          "  SELECT p_inout, p_in, substring(p_out, 9);"
+                         "END");
+  myquery(rc);
+
+  stmt= mysql_stmt_init(mysql);
+  DIE_UNLESS(stmt != NULL);
+
+  rc= mysql_stmt_prepare(stmt, "CALL P1(?,?,?)", 14);
+  DIE_UNLESS(rc == 0);
+
+  DIE_UNLESS(mysql_stmt_param_count(stmt) == 3);
+
+  memset(bind, 0, sizeof(MYSQL_BIND) * 3);
+  for (i=0; i < 3; i++)
+  {
+    bind[i].buffer= &a[i];
+    bind[i].buffer_type= MYSQL_TYPE_LONG;
+  }
+  bind[0].buffer_type= MYSQL_TYPE_NULL;
+  rc= mysql_stmt_bind_param(stmt, bind);
+  DIE_UNLESS(rc == 0);
+
+  rc= mysql_stmt_execute(stmt);
+  DIE_UNLESS(rc == 0);
+
+  rc= mysql_stmt_fetch(stmt);
+  DIE_UNLESS(rc == 0);
+
+  rc= mysql_stmt_reset(stmt);
+  DIE_UNLESS(rc == 0);
+
+  /*connection shouldn't be blocked now */
+
+  rc= mysql_query(mysql, "DROP PROCEDURE p1");
+  myquery(rc);
+
+  /* 2nd test:
+     reset all result sets */
+  rc= mysql_query(my, "CREATE PROCEDURE p1() "
+                      "BEGIN"
+                      "  SELECT 1,2,3 FROM DUAL;"
+                      "  SELECT 'foo' FROM DUAL;"
+                      "END");
+  myquery(rc);
+
+  rc= mysql_stmt_prepare(stmt, "CALL P1()", 9);
+  DIE_UNLESS(rc == 0);
+
+  rc= mysql_stmt_execute(stmt);
+  DIE_UNLESS(rc == 0);
+
+  rc= mysql_stmt_reset(stmt);
+  DIE_UNLESS(rc == 0);
+
+  /* 3rd test:
+     mysql_stmt_close should also flush all pending
+     result sets
+  */
+  
+  rc= mysql_stmt_prepare(stmt, "CALL P1()", 9);
+  DIE_UNLESS(rc == 0);
+
+  rc= mysql_stmt_execute(stmt);
+  DIE_UNLESS(rc == 0);
+
+  rc= mysql_stmt_close(stmt);
+  DIE_UNLESS(rc == 0);
+
+  rc= mysql_query(my, "DROP PROCEDURE p1");
+  myquery(rc);
+
+  mysql_close(my);
+}
 
 static struct my_tests_st my_tests[]= {
   { "disable_query_logs", disable_query_logs },
@@ -19109,12 +19212,13 @@
   { "test_bug58036", test_bug58036 },
   { "test_bug57058", test_bug57058 },
   { "test_bug56976", test_bug56976 },
-  { "test_mdev3885", test_mdev3885 },
+  { "test_mdev3885", test_mdev3885 }, 
   { "test_bug11766854", test_bug11766854 },
   { "test_bug12337762", test_bug12337762 },
   { "test_progress_reporting", test_progress_reporting },
   { "test_bug11754979", test_bug11754979 },
   { "test_bug13001491", test_bug13001491 },
+  { "test_mdev_4603", test_mdev_4603 },
   { 0, 0 }
 };
 

