Search code examples
c#api.net-coreodbcassert

Assertion Failed when opening a second OdbcConnection


I wrote an API that connects to a Sybase Backend using .net Core 3.1

It needs to open an ODBC connection to a Sybase database when it gets called.

If I call it after the API comes up it works just fine. I can even call it hundreds of times in a row.

However when I wait 90 seconds and call the API again with the same call I get an Assert Failure popup window in the Microsoft C++ runtime library threads.c that looks like this:

*Application popup: Microsoft Visual C++ Runtime Library : Assertion failed!
Program: c:\windows\system32\inetsrv\w3wp.exe
File: .\threads.c
Line: 334
Expression: destructors_set[keynum] == 0
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts
(Press Retry to debug the application - JIT must be enabled)*

It happens consistently on the connection.Open(); instruction.

It pops up on the server or locally when I'm debigging and crashes the IIS worker thread on the server or IISExpress when I'm debugging. The API crashes when you abort and then when it's restarted it has the exact same behavior. If I click ignore on the alert it completes normally.

I tried running the DbConnect class as a Singleton, Scoped and even a Transient object in the injection container. I even tried removing all the dependency injection in case those were causing the problem. They all do the same. I don't know what to check anymore.

public class DbConnect : IDbConnect
{
    private ILogger<DbConnect> _logger;

    public DbConnect(ILogger<DbConnect> logger)
    {
        _logger = logger;
    }
    public DataTable OdbcSelectQueryNew(string query)
    {
        DataTable dt = new DataTable();
        string connStr = "";//<--- removed for brevity and hard-coded for testing
        try
        {
            using (var connection = new OdbcConnection(connStr))
            {
                connection.Open();
                OdbcCommand command = new OdbcCommand(query);
                command.Connection = connection;
                OdbcDataAdapter adapter = new OdbcDataAdapter(command);
                adapter.Fill(dt);
            } 
            return dt;
        }
        catch (Exception e)
        {
            _logger.LogError("Log the error", e.ToString());
            throw;
        }
    }
}

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }
    
    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        services.AddSingleton<IComLog, ComLog>();
        services.AddHttpContextAccessor();
        services.AddSingleton<IDbConnect, DbConnect>();
    }
}

Solution

  • I got this working by getting rid entirely of MIT-Kerberos. It's just not stable.

    I am using the windows built-in authentication for kerberos tickets now and it seems to be stable and doesn't crash my app pool.

    My connection string looks like this now: Driver={Adaptive Server Enterprise};server=fakeservername;port=5050;Database=fakedbname;AuthenticationClient=activedirectory;[email protected];[email protected];PacketSize=4096;Max Pool Size=250;

    where the fakeuserprincipal is the user my app pool uses for it's identity and the fakeuserprincipal is the Sybase host's ID as defined in the kerberos spn.