Bug #80997 Fix for "Aborted connection"
Submitted: 7 Apr 2016 12:51 Modified: 29 Jun 2016 20:43
Reporter: Michiel Hazelhof Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / NET Severity:S3 (Non-critical)
Version:6.9.8 OS:Windows
Assigned to: Gabriela Martinez Sanchez CPU Architecture:Any
Tags: aborted, Connection, fix

[7 Apr 2016 12:51] Michiel Hazelhof
Description:
The DotNet connector incorrectly marks the connection as closed in some cases causing error messages on the server side: "<date> <time> <epoch> [Warning] Aborted connection <thread> to db: '<db>' user: '<user>' host: '<host>' (Unknown error).

How to repeat:
Close the driver with dispoising = false and then close it with disposing = true.

Suggested fix:
Only set the isOpen boolean to false when we have actually closed the connection.

NativeDriver.cs:

        protected virtual void Dispose(bool disposing)
        {
            // Avoid cyclic calls to Dispose.
            if (disposeInProgress) return;
            disposeInProgress = true;

            try
            {
                ResetTimeout(1000);
                if (disposing)
                {
                    handler.Close(isOpen);
                    isOpen = false;
                }
                // if we are pooling, then release ourselves
                if (connectionString.Pooling)
                    MySqlPoolManager.RemoveConnection(this);
            }
            catch (Exception)
            {
                if (disposing)
                    throw;
            }
            finally
            {
                reader = null;
                disposeInProgress = false;
            }
        }
[8 Apr 2016 8:04] Michiel Hazelhof
That should be Driver.cs, my mistake.
[10 May 2016 9:25] Chiranjeevi Battula
Hello  Michiel Hazelhof,

Thank you for the bug report.
Could you please provide repeatable test case (exact steps/sample project, connection string etc. - please make it as private if you prefer) to confirm this issue at our end?

Thanks,
Chiranjeevi.
[10 May 2016 14:54] Michiel Hazelhof
This mainly happens due to garbage collection, so it is hard to write an example for this. (haven't been able to point the finger to the exact sour spot unfortunately).

The only thing this patch basically does is correctly set the isOpen variable to false when we close the connection.

This has dramatically reduced the warnings on our server (about 95%).
[11 May 2016 6:40] Chiranjeevi Battula
Hello  Michiel Hazelhof,

Thank you for your feedback.
I could not repeat this issue at my end with the provided information. 
If you can provide more information, feel free to add it to this bug and change the status back to 'Open'.

Thank you for your interest in MySQL.

Thanks,
Chiranjeevi.
[16 May 2016 15:11] Michiel Hazelhof
Please edit the last comment, forgot to remove the connection string for the test db
[25 May 2016 12:51] Chiranjeevi Battula
Hello Michiel Hazelhof,

Thank you for your feedback and test case.
Verified this behavior on Visual Studio 2013 (C#.Net) and Connector/NET 6.9.8 version.

Thanks,
Chiranjeevi.
[25 May 2016 12:51] Chiranjeevi Battula
Aborted connections:

2016-05-25 18:13:08 12336 [Warning] Aborted connection 5 to db: 'test' user: 'root' host: 'localhost' (Got an error reading communication packets)
2016-05-25 18:15:00 12336 [Warning] Aborted connection 8 to db: 'test' user: 'root' host: 'localhost' (Got an error reading communication packets)
2016-05-25 18:16:25 12336 [Warning] Aborted connection 9 to db: 'test' user: 'root' host: 'localhost' (Got an error reading communication packets)
2016-05-25 18:18:14 12336 [Warning] Aborted connection 10 to db: 'test' user: 'root' host: 'localhost' (Got an error reading communication packets)
[6 Jun 2016 19:37] Gabriela Martinez Sanchez
There are certain scenarios where the GC will send and object to free up its resources. These scenarios are correct since the connection has become idle or inactive. We would like to ask you if you could share how are you handling the connections in your application.
Could you please add the relevant code in order to continue troubleshooting this issue?

Thanks in advance for your feedback.
[6 Jun 2016 20:30] Michiel Hazelhof
I don't keep idle connections, either they get disconnected after a few minutes or they are actively kept alive.

Mostly these just happen when somebody closes the application (like in the example).

When reading the source code it is obvious that this would happen.
[6 Jun 2016 21:25] Gabriela Martinez Sanchez
There should be a method or event where you can handle this user case. If you do not handle it then the GC will do what is best to free up the resources that are left, and thus the server will close the connection. Have you tried to add this type of event in your application code?
[6 Jun 2016 21:43] Michiel Hazelhof
Yes, all connections are properly closed and where possible disposed.

As proven by the example (and verified by Chiranjeevi Battula) this is a real problem, even when closing and disposing a connection.
[7 Jun 2016 19:55] Gabriela Martinez Sanchez
hi again,
I was able to reproduce the scenario you described. And I also applied the fix. I noticed that there are still some scenarios where the fix won't make any difference. Like when closing the console application with the X button. In these cases you would need to handle the disposing in your application. It would be really good if you can find a case where after the fix you made the connections are still aborted.
Have you identified any?

Thanks in advance.
[9 Jun 2016 20:34] Michiel Hazelhof
I'll take a look into some more cases, this patch has fixed most scenarios for our solution.

using a destructor like the following also cures some problems.

~Connector()
{
    _mysql?.Close();
    _mysql?.Dispose();
}
[10 Jun 2016 16:11] Michiel Hazelhof
private static readonly SimpleHelper Connection = new SimpleHelper();
        public static void Main(string[] args)
        {
            try
            {
                Connection.Connection.Open();
            }
            catch (MySqlException ex)
            {
                Console.WriteLine(ex.Message);
            }
            
            Environment.Exit(0);
        }

    public class SimpleHelper : IDisposable
    {
        public MySqlConnection Connection = new MySqlConnection { ConnectionString = "<fillme>" };

        ~SimpleHelper()
        {
            Dispose();
        }

        public void Dispose()
        {
            Connection?.Close();
            Connection?.Dispose();
        }
    }

However when closing a console applicaton with the X button the destructors are not called (Environment.Exit() will call them), so we cannot fix situations where there are open connections (this behaviour differs from the Winforms where it is effective).

We have something like the above "SimpleHelper" with a timer and a lot of functions to ease the usage of the database connection. Combined with another class filled with extension methods it is more or less foolproof solution.
[29 Jun 2016 20:43] Philip Olson
Fixed as of the upcoming Connector/Net 6.9.9 release, and here's the changelog entry:

Improvements were made to how the connector handles aborted connections.

Thank you for the bug report.