Example #1
0
        private static Thread StartEvilThread(EvilThreadArgument arg)
        {
            ThreadStart entry = () => {
                arg.ExceptionType = null;
                try {
                    using (var command = arg.Connection.CreateCommand(arg.Statement)) {
                        arg.StartEvent.WaitOne();
                        command.ExecuteNonQuery();
                    }
                }
                catch (Exception exception) {
                    arg.ExceptionType = arg.Connection.Driver.GetExceptionType(exception);
                }
                arg.Connection.Rollback();
            };

            var thread = new Thread(entry);

            thread.Start();
            return(thread);
        }
Example #2
0
        public virtual void DeadlockTest()
        {
            var table = schema.CreateTable(DeadlockTableName);

            CreatePrimaryKey(table);
            var column = table.CreateColumn("value", Driver.TypeMappings[typeof(int)].MapType());

            column.IsNullable = true;
            ExecuteNonQuery(SqlDdl.Create(table));

            Connection.BeginTransaction();
            var tableRef = SqlDml.TableRef(table);
            var insert   = SqlDml.Insert(tableRef);

            insert.Values.Add(tableRef[IdColumnName], 1);
            ExecuteNonQuery(insert);
            insert.Values.Clear();
            insert.Values.Add(tableRef[IdColumnName], 2);
            ExecuteNonQuery(insert);
            Connection.Commit();

            var update1To1 = SqlDml.Update(tableRef);

            update1To1.Where = tableRef[IdColumnName] == 1;
            update1To1.Values.Add(tableRef[column.Name], 1);

            var update1To2 = SqlDml.Update(tableRef);

            update1To2.Where = tableRef[IdColumnName] == 1;
            update1To2.Values.Add(tableRef[column.Name], 2);

            var update2To1 = SqlDml.Update(tableRef);

            update2To1.Where = tableRef[IdColumnName] == 2;
            update2To1.Values.Add(tableRef[column.Name], 1);

            var update2To2 = SqlDml.Update(tableRef);

            update2To2.Where = tableRef[IdColumnName] == 2;
            update2To2.Values.Add(tableRef[column.Name], 2);
            using (var connectionOne = this.Driver.CreateConnection()) {
                connectionOne.Open();
                connectionOne.BeginTransaction(IsolationLevel.ReadCommitted);

                using (var connectionTwo = Driver.CreateConnection()) {
                    connectionTwo.Open();
                    connectionTwo.BeginTransaction(IsolationLevel.ReadCommitted);

                    using (var command = connectionOne.CreateCommand(update1To1))
                        command.ExecuteNonQuery();
                    using (var command = connectionTwo.CreateCommand(update2To2))
                        command.ExecuteNonQuery();

                    var startEvent = new EventWaitHandle(false, EventResetMode.ManualReset);
                    var arg1       = new EvilThreadArgument
                    {
                        Connection = connectionOne,
                        StartEvent = startEvent,
                        Statement  = update2To1
                    };
                    var arg2 = new EvilThreadArgument
                    {
                        Connection = connectionTwo,
                        StartEvent = startEvent,
                        Statement  = update1To2
                    };
                    var thread1 = StartEvilThread(arg1);
                    var thread2 = StartEvilThread(arg2);
                    startEvent.Set();
                    thread1.Join();
                    thread2.Join();
                    startEvent.Close();
                    var actual = arg1.ExceptionType ?? arg2.ExceptionType ?? SqlExceptionType.Unknown;
                    AssertExceptionType(SqlExceptionType.Deadlock, actual);
                }
            }
        }