How do I avoid "Access Violation" during asynchronous database connections?

1

Goal: Using ExecuteAsync correctly.

I know my application itself is at least pretty close to correct because it executes correctly once, so I know I can eliminate the usual suspects of firewalls, wrong database passwords, procedure names, etc.

private async Task<T> executeAsyncHelper<T>(Func<IDataReader, T> then)
{
    using (SqlConnection conn = new SqlConnection(connectionString))
    {
        conn.Open();
        using (SqlCommand cmd = new SqlCommand(name, conn))
        {
            parameters.Select(p => cmd.Parameters.Add(p))
                .ToImmutableList(); 
            cmd.CommandType = CommandType.StoredProcedure;
            using (IDataReader rdr = await cmd.ExecuteReaderAsync())
            {
                return then(rdr);
            }
        }
    }
}

The Issue: Access Violation on the Second SqlConnection.Open()

The method gets called twice on the same procedure. The first time, it successfully updates the database. The second time, the whole thing dumps out on conn.Open() with "Access violation." Importantly, it's not throwing an exception. Rather, the whole debugger exits with a negative status code.

These are the last two lines of the debugger output (The rest of the debugger output looks normal):

The program '[6904] dotnet.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'.  
The program '[6904] dotnet.exe: Program Trace' has exited with code 0 (0x0).

This behavior is 100% repeatable.

Hypothesis: Connection Pooling and Asynchronicity

As far as I can see, the most probable cause is that there's some problem with opening two connections asynchronously, but I don't immediately know what to do with that hypothesis. I've written the method as safely as I know how.

Secondarily, I checked to see if my Azure SQL Server instance had any unusual limitations on it. It's a basic instance, but I doubt that's the issue since I would expect a SQL exception (that the debugger will break on and show a normal stack trace) if that were the problem.

Environmental information

  • Azure SQL Server 2016
  • Windows 10
  • .NET Core 2.1
  • Visual Studio 2017

Conclusion

Does anyone see any problem with the way I've implemented this or have any suggestions to learn more about the error?

c#
.net-core
ado.net
task-parallel-library
sqlconnection

3 Answers

0

Try this:

private async Task<T> executeAsyncHelper<T>(Func<IDataReader, Task<T>> then)
{
    using (SqlConnection conn = new SqlConnection(connectionString))
    {
        conn.Open();
        using (SqlCommand cmd = new SqlCommand(name, conn))
        {
            parameters.Select(p => cmd.Parameters.Add(p))
                .ToImmutableList(); 
            cmd.CommandType = CommandType.StoredProcedure;
            using (IDataReader rdr = await cmd.ExecuteReaderAsync())
            {
                return await then(rdr);
            }
        }
    }
}

Note the changes to the signature, and awaiting on return.

answered on Stack Overflow Jun 1, 2020 by Moo-Juice
0

Just so you can check that you're not hitting a connection limit, you can do exec sp_who2 and see how many connections are on your sql server. If there are a lot of connections shown on the sql server, that maybe the cause due to resource issues. Have you try running this code in the regular synchronously and did it cause the same issue? Is there anything on your connection string that limits the number of connections? Just some theory to throw out since I don't see the context of this code.

answered on Stack Overflow Jun 1, 2020 by Matthew Nguyen
0

Pretty confident I figured it out. It didn't actually have anything to do with the precise line where the program was dying.

Rather, the program was overflowing the stack elsewhere on a different thread. The conn.Open() was a red herring, even though that's where the debugger always pointed just before it failed. My guess is that conn.Open() is just resource intensive enough to put it over the edge to make it look like that was causing it.

For future reference, if you get "Access violation," refactor to synchronous code, and then the debugger will be able to walk straight through and actually throw the StackOverflowException instead of just crashing.

answered on Stack Overflow Jun 3, 2020 by Eleanor Holley

User contributions licensed under CC BY-SA 3.0