MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Vladislav Vaintroub Date:June 28 2010 10:05pm
Subject:bzr commit into connector-net-6.2 branch (vvaintroub:865) Bug#54012
View as plain text  
#At file:///H:/connector_net/6.2/ based on revid:reggie.burnett@stripped

  865 Vladislav Vaintroub	2010-06-29
      Cancel query in ThreadAbortException handler (Bug#54012)

    modified:
      CHANGES
      MySql.Data/Provider/Source/Connection.cs
      MySql.Data/Provider/Source/command.cs
      MySql.Data/Provider/Source/datareader.cs
      MySql.Data/Tests/Source/Threading.cs
=== modified file 'CHANGES'
--- a/CHANGES	2010-06-25 21:46:56 +0000
+++ b/CHANGES	2010-06-28 22:05:53 +0000
@@ -1,3 +1,4 @@
+- Cancel query in ThreadAbortException handler (Bug#54012)
 - Fix race condition (concurrent reading/modification of the same DataSet) in StoredProcedure.GetParameters()
   (bug#49118)
 - Fix problems with MySqlDataAdapter insert command, when batch size is > 1, and 

=== modified file 'MySql.Data/Provider/Source/Connection.cs'
--- a/MySql.Data/Provider/Source/Connection.cs	2010-06-16 11:53:26 +0000
+++ b/MySql.Data/Provider/Source/Connection.cs	2010-06-28 22:05:53 +0000
@@ -52,7 +52,7 @@ namespace MySql.Data.MySqlClient
 #if !CF
         private PerformanceMonitor perfMonitor;
 #endif
-        private bool abortOnTimeout;
+        private bool isKillQueryConnection;
         private string database;
         private int commandTimeout;
 
@@ -629,17 +629,23 @@ namespace MySql.Data.MySqlClient
 
 
 
-        internal void HandleTimeout(TimeoutException tex)
+        internal void HandleTimeoutOrThreadAbort(Exception ex)
         {
             bool isFatal = false;
 
-            if (abortOnTimeout)
+            if (isKillQueryConnection)
             {
                 // Special connection started to cancel a query.
-                // Timeout handler is disabled to prevent recursive connection
-                // spawning when original query and KILL time out.
+                // Abort will prevent recursive connection spawning
                 Abort();
-                throw new MySqlException(Resources.Timeout, true , tex);
+                if (ex is TimeoutException)
+                {
+                    throw new MySqlException(Resources.Timeout, true, ex);
+                }
+                else
+                {
+                    return;
+                }
             }
 
             try
@@ -659,14 +665,17 @@ namespace MySql.Data.MySqlClient
                     Reader = null;
                 }
             }
-            catch (Exception ex)
+            catch (Exception ex2)
             {
-                MySqlTrace.LogWarning(ServerThread, "Could not kill query in timeout handler, " +
-                    " aborting connection. Exception was " + ex.Message);
+                MySqlTrace.LogWarning(ServerThread, "Could not kill query, " +
+                    " aborting connection. Exception was " + ex2.Message);
                 Abort();
                 isFatal = true;
             }
-            throw new MySqlException(Resources.Timeout, isFatal, tex);
+            if (ex is TimeoutException)
+            {
+                throw new MySqlException(Resources.Timeout, isFatal, ex);
+            }
         }
 
         public void CancelQuery(int timeout)
@@ -681,7 +690,7 @@ namespace MySql.Data.MySqlClient
           
             using(MySqlConnection c = new MySqlConnection(cb.ConnectionString))
             {
-                c.abortOnTimeout = true;
+                c.isKillQueryConnection = true;
                 c.Open();
                 string commandText = "KILL QUERY " + ServerThread;
                 MySqlCommand cmd = new MySqlCommand(commandText, c);

=== modified file 'MySql.Data/Provider/Source/command.cs'
--- a/MySql.Data/Provider/Source/command.cs	2010-06-17 00:26:23 +0000
+++ b/MySql.Data/Provider/Source/command.cs	2010-06-28 22:05:53 +0000
@@ -437,8 +437,13 @@ namespace MySql.Data.MySqlClient
             }
             catch (TimeoutException tex)
             {
-                connection.HandleTimeout(tex);
-                return null;
+                connection.HandleTimeoutOrThreadAbort(tex);
+                throw; //unreached
+            }
+            catch (ThreadAbortException taex)
+            {
+                connection.HandleTimeoutOrThreadAbort(taex);
+                throw;
             }
             catch (MySqlException ex)
             {

=== modified file 'MySql.Data/Provider/Source/datareader.cs'
--- a/MySql.Data/Provider/Source/datareader.cs	2010-06-10 21:34:13 +0000
+++ b/MySql.Data/Provider/Source/datareader.cs	2010-06-28 22:05:53 +0000
@@ -876,8 +876,13 @@ namespace MySql.Data.MySqlClient
             }
             catch (TimeoutException tex)
             {
-                connection.HandleTimeout(tex);
-                return false; // unreached
+                connection.HandleTimeoutOrThreadAbort(tex);
+                throw; // unreached
+            }
+            catch (System.Threading.ThreadAbortException taex)
+            {
+                connection.HandleTimeoutOrThreadAbort(taex);
+                throw;
             }
             catch (MySqlException ex)
             {

=== modified file 'MySql.Data/Tests/Source/Threading.cs'
--- a/MySql.Data/Tests/Source/Threading.cs	2009-10-09 20:38:36 +0000
+++ b/MySql.Data/Tests/Source/Threading.cs	2010-06-28 22:05:53 +0000
@@ -120,6 +120,48 @@ namespace MySql.Data.MySqlClient.Tests
 				x++;
 			}
 		}
-	}
+        /// <summary>
+        /// Bug #54012  	MySql Connector/NET is not hardened to deal with 
+        /// ThreadAbortException
+        /// </summary>
+        private void HardenedThreadAbortExceptionWorker()
+        {
+            try
+            {
+                using (MySqlConnection c = new MySqlConnection(GetConnectionString(true)))
+                {
 
+                    c.Open();
+                    MySqlCommand cmd = new MySqlCommand(
+                        "SELECT BENCHMARK(10000000000,ENCODE('hello','goodbye'))",
+                        c);
+                    // ThreadAbortException is not delivered, when thread is 
+                    // stuck in system call. To shorten test time, set command 
+                    // timeout to a small value. Note .shortening command timeout
+                    // means we could actually have timeout exception here too, 
+                    // but it seems like CLR delivers ThreadAbortException, if 
+                    // the  thread was aborted.
+                    cmd.CommandTimeout = 2;
+                    cmd.ExecuteNonQuery();
+                }
+            }
+            catch (ThreadAbortException)
+            {
+                Thread.ResetAbort();
+                return;
+            }
+            Assert.Fail("expected ThreadAbortException");
+        }
+
+        [Test]
+        public void HardenedThreadAbortException()
+        {
+            Thread t = new Thread(new ThreadStart(HardenedThreadAbortExceptionWorker));
+            t.Name = "Execute Query";
+            t.Start();
+            Thread.Sleep(500);
+            t.Abort();
+            t.Join();
+        }
+    }
 }


Attachment: [text/bzr-bundle] bzr/vvaintroub@mysql.com-20100628220553-hul8dls4r3ej4hi8.bundle
Thread
bzr commit into connector-net-6.2 branch (vvaintroub:865) Bug#54012Vladislav Vaintroub29 Jun