-
Notifications
You must be signed in to change notification settings - Fork 348
Closed
Description
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.
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.InvalidOperationException
at MySqlConnector.MySqlConnection.get_Session()
at MySqlConnector.MySqlConnection.get_ServerThread()
at MySqlConnector.MySqlConnection.Cancel(MySqlConnector.Core.ICancellableCommand, Int32, Boolean)
at MySqlConnector.Utilities.TimerQueue.Callback(System.Object)
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.TimerQueueTimer.CallCallback()
at System.Threading.TimerQueueTimer.Fire()
at System.Threading.TimerQueue.FireNextTimers()
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
internal void Cancel(ICancellableCommand command, int commandId, bool isCancel)
{
// Bug report comment:
// Session is not null and open.
if (m_session is null || State != ConnectionState.Open || !m_session.TryStartCancel(command))
{
Log.Info("Ignoring cancellation for closed connection or invalid CommandId {0}", commandId);
return;
}
Log.Info("CommandId {0} for Session{1} has been canceled via {2}.", commandId, m_session.Id, isCancel ? "Cancel()" : "command timeout");
try
{
// open a dedicated connection to the server to kill the active query
var csb = new MySqlConnectionStringBuilder(m_connectionString);
csb.Pooling = false;
if (m_session.IPAddress is not null)
csb.Server = m_session.IPAddress.ToString();
var cancellationTimeout = GetConnectionSettings().CancellationTimeout;
csb.ConnectionTimeout = cancellationTimeout < 1 ? 3u : (uint) cancellationTimeout;
using var connection = new MySqlConnection(csb.ConnectionString);
connection.Open();
// Bug report comment
// command.Connection!.ServerThread will call Session property where we assert that the state is Open which it is not anymore.
using var killCommand = new MySqlCommand("KILL QUERY {0}".FormatInvariant(command.Connection!.ServerThread), connection);
killCommand.CommandTimeout = cancellationTimeout < 1 ? 3 : cancellationTimeout;
m_session.DoCancel(command, killCommand);
}
catch (MySqlException ex)
{
// cancelling the query failed; setting the state back to 'Querying' will allow another call to 'Cancel' to try again
Log.Warn(ex, "Session{0} cancelling CommandId {1} failed", m_session!.Id, command.CommandId);
m_session.AbortCancel(command);
}
}
Metadata
Metadata
Assignees
Labels
No labels