-
Notifications
You must be signed in to change notification settings - Fork 329
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unhandled exception in MySqlConnector.Utilities.TimerQueue.Callback #1002
Comments
Looks like MySqlConnection.Cancel expects only MySqlExceptions but MySqlConnection.Session throws an InvalidOperationException. Just ran into this as well but instead it causes a dead-lock for us because we attempt to log unhandled exceptions to a mysql db using log4net. So one thread holds a lock in log4net and waits for the lock in TimerQueue.Remove and another thread holds the lock in TimerQueue.Callback and waits for the lock in log4net. At least that is what it looks like in the dump file. |
@bjornhandersson Do you know what the I don't know why this line accesses
It seems like we might be able to save the |
I'm trying to reproduce this race condition with a stress test that runs lots of
Any pointers on how to reproduce this reliably? |
In my dump files the InvalidOperationException's message is:
Don't have a way to reproduce yet. |
Looks like the ServerSesssion for the connection has State = Failed. So it could be that at the same time as the TimerQueue triggered a cancel the server responded with something (or closed the connection) causing the ServerSession.State to be changed to Failed. ServerSesssion.SetFailed also sets the connection state to Closed. |
Unfortunately I don't know what the Guess there are three potential "fixes"
|
Yes, but Edit: Handling |
I found an interesting lock dependency in the code when I was trying to run my repro: using var connection = new MySqlConnection(csb.ConnectionString);
connection.Open();
using var command = new MySqlCommand($"DO SLEEP(1.00);", connection) { CommandTimeout = 1 };
command.ExecuteNonQuery(); My hypothesis was that the command could finish executing and dispose the connection before cancellation completes. However, I found that when the command is being cancelled, MySqlConnector/src/MySqlConnector/Utilities/TimerQueue.cs Lines 72 to 74 in b7a82b1
But so does MySqlConnector/src/MySqlConnector/Utilities/TimerQueue.cs Lines 48 to 50 in b7a82b1
Which is called from MySqlConnector/src/MySqlConnector/MySqlDataReader.cs Lines 571 to 580 in b7a82b1
Thus, disposing the data reader can't complete until the command timeout callback is removed from the queue, which can't happen (due to the lock) until the command timeout callback (which cancels the command) completes running. (One could probably simulate this race condition by explicitly calling |
Shipped a fix in 1.3.10 that catches and ignores the |
Possibly related to: #820
Version:
1.3.4
An unhandled exception in
MySqlConnector.Utilities.TimerQueue.Callback
crashes the process without giving the user a chance to handle it.By looking at the code it looks like the state of the connections changes meanwhile canceling the command.
I added line comments in the snippet below to explain the issue.
// Bug report comment:
// My comment.
MySqlConnection.Cancel
The text was updated successfully, but these errors were encountered: