Skip to content

Throw a specific exception for deadlocks #11

Closed

Description

@oliverhanappi

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

Activity

  1. madelson commented on Nov 15, 2017

    @madelson
    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.

  2. oliverhanappi commented on Nov 15, 2017

    @oliverhanappi
    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();
          }
        }
      }
    }
    
  3. added 2 commits that reference this issue on Feb 7, 2018
  4. madelson commented on Feb 8, 2018

    @madelson
    Owner

    This is addressed as of version 1.4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions