Skip to content

Unhandled exception in MySqlConnector.Utilities.TimerQueue.Callback #1002

@bjornhandersson

Description

@bjornhandersson

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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions