Skip to content
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

Throw a specific exception for deadlocks #11

Closed
oliverhanappi opened this issue Nov 15, 2017 · 3 comments
Closed

Throw a specific exception for deadlocks #11

oliverhanappi opened this issue Nov 15, 2017 · 3 comments

Comments

@oliverhanappi
Copy link

The method SqlApplicationLock.ParseExitCode throws an InvalidOperationException when a deadlock is detected. It would be very useful if a specific exception would be thrown.

@madelson
Copy link
Owner

Hi @oliverhanappi thank you for your interest in the library.

I'm curious whether you've ever seen the deadlock exit code returned. I remember trying to force this a while back and not seeing it.

Provided we can create a test case where this is actually returned, this suggestion makes sense and would be an easy enhancement. For backwards compat, the new exception should extend InvalidOperationException.

@oliverhanappi
Copy link
Author

It is actually pretty easy. You just need to acquire multiple locks within the same connection or transaction such that two connections/transactions are waiting on each other. Here is a simple repro:

using System;
using System.Data.SqlClient;
using System.Threading;
using System.Threading.Tasks;
using Medallion.Threading.Sql;

namespace SqlDistributedLockDeadlock
{
  public static class Program
  {
    public static void Main ()
    {
      using (var barrier = new Barrier (2))
      {
        var task1 = Task.Run (() => WithTransaction((connection, transaction) =>
        {
          new SqlDistributedLock ("test1", transaction).Acquire();
          barrier.SignalAndWait();
          new SqlDistributedLock ("test2", transaction).Acquire();
        }));
        
        var task2 = Task.Run (() => WithTransaction((connection, transaction) =>
        {
          new SqlDistributedLock ("test2", transaction).Acquire();
          barrier.SignalAndWait();
          new SqlDistributedLock ("test1", transaction).Acquire();
        }));

        Task.WaitAll (task1, task2);
      }
    }

    private static void WithTransaction (Action<SqlConnection, SqlTransaction> action)
    {
      const string connectionString = "Server=localhost;Database=Playground;Integrated Security=True";

      using (var connection = new SqlConnection (connectionString))
      {
        connection.Open();

        using (var transaction = connection.BeginTransaction())
          action.Invoke (connection, transaction);

        connection.Close();
      }
    }
  }
}

madelson added a commit that referenced this issue Feb 7, 2018
madelson added a commit that referenced this issue Feb 7, 2018
Address #11 by throwing a specific exception type (DeadlockException)…
@madelson
Copy link
Owner

madelson commented Feb 8, 2018

This is addressed as of version 1.4

@madelson madelson closed this as completed Feb 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants