打开第二个 OdbcConnection 时断言失败
Assertion Failed when opening a second OdbcConnection
我写了一个 API 使用 .net Core 3.1
连接到 Sybase 后端
它需要在被调用时打开一个到 Sybase 数据库的 ODBC 连接。
如果我在 API 出现后调用它,它就可以正常工作。我什至可以连续调用它数百次
然而,当我等待 90 秒并使用相同的调用再次调用 API 时,我在 Microsoft C++ 运行时库 threads.c 中得到一个 Assert Failure 弹出窗口 window,看起来像这样:
*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)*
它一直发生在 connection.Open() 上;说明。
它在我调试时在服务器上或本地弹出,并在我调试时使服务器或 IISExpress 上的 IIS 工作线程崩溃。 API 在您中止时崩溃,然后在重新启动时它具有完全相同的行为。如果我在警报上单击忽略,它会正常完成。
我尝试 运行 DbConnect class 作为注入容器中的 Singleton、Scoped 甚至 Transient 对象。我什至尝试删除所有依赖项注入,以防它们导致问题。他们都这样做。我不知道该检查什么了。
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>();
}
}
我找到了造成这种情况的根本原因。虽然没有说明,因为我从来没有想过它可能会导致问题,但当我使用 mitkerberos 作为身份验证客户端时,就会发生这种情况。
我的连接字符串如下所示:
Driver={Adaptive Server Enterprise};server=fakeservername;port=5050;Database=fakedbname;AuthenticationClient=mitkerberos;ServerPrincipal=fakeserverprincipal@fakedomain.COM
如果我恢复到具有 username/pwd 的 connectionString,如下所示:
Driver={Adaptive Server Enterprise};server=fakeservername;port=5050;UID=fakeuserid;PWD=fakepassword;Database=fakedatabase;PacketSize=4096;Persist Security Info=true;Max Pool Size=250;
一切都很好,错误从未发生,后续连接正常工作。
我不知道如何解决这个问题。也许是麻省理工学院的 Kerberos 客户端有缺陷?我不确定现在如何使用 kerberos 身份验证连接到远程数据库,但至少找到了断言失败的根本原因。
我通过完全摆脱 MIT-Kerberos 来实现这个功能。就是不稳定。
我现在正在使用 windows 内置的 kerberos 票证身份验证,它似乎很稳定,不会使我的应用程序池崩溃。
我的连接字符串现在看起来像这样:
Driver={Adaptive Server Enterprise};server=fakeservername;port=5050;Database=fakedbname;AuthenticationClient=activedirectory;UserPrincipal=fakeuserprincipal@FAKEDOMAIN.COM;ServerPrincipal=fakeserverprincipal@FAKEDOMAIN.COM;PacketSize=4096;Max Pool尺寸=250;
其中 fakeuserprincipal 是我的应用程序池用于其身份的用户,fakeuserprincipal 是 kerberos spn 中定义的 Sybase 主机 ID。
我写了一个 API 使用 .net Core 3.1
连接到 Sybase 后端它需要在被调用时打开一个到 Sybase 数据库的 ODBC 连接。
如果我在 API 出现后调用它,它就可以正常工作。我什至可以连续调用它数百次
然而,当我等待 90 秒并使用相同的调用再次调用 API 时,我在 Microsoft C++ 运行时库 threads.c 中得到一个 Assert Failure 弹出窗口 window,看起来像这样:
*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)*
它一直发生在 connection.Open() 上;说明。
它在我调试时在服务器上或本地弹出,并在我调试时使服务器或 IISExpress 上的 IIS 工作线程崩溃。 API 在您中止时崩溃,然后在重新启动时它具有完全相同的行为。如果我在警报上单击忽略,它会正常完成。
我尝试 运行 DbConnect class 作为注入容器中的 Singleton、Scoped 甚至 Transient 对象。我什至尝试删除所有依赖项注入,以防它们导致问题。他们都这样做。我不知道该检查什么了。
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>();
}
}
我找到了造成这种情况的根本原因。虽然没有说明,因为我从来没有想过它可能会导致问题,但当我使用 mitkerberos 作为身份验证客户端时,就会发生这种情况。
我的连接字符串如下所示:
Driver={Adaptive Server Enterprise};server=fakeservername;port=5050;Database=fakedbname;AuthenticationClient=mitkerberos;ServerPrincipal=fakeserverprincipal@fakedomain.COM
如果我恢复到具有 username/pwd 的 connectionString,如下所示:
Driver={Adaptive Server Enterprise};server=fakeservername;port=5050;UID=fakeuserid;PWD=fakepassword;Database=fakedatabase;PacketSize=4096;Persist Security Info=true;Max Pool Size=250; 一切都很好,错误从未发生,后续连接正常工作。
我不知道如何解决这个问题。也许是麻省理工学院的 Kerberos 客户端有缺陷?我不确定现在如何使用 kerberos 身份验证连接到远程数据库,但至少找到了断言失败的根本原因。
我通过完全摆脱 MIT-Kerberos 来实现这个功能。就是不稳定。
我现在正在使用 windows 内置的 kerberos 票证身份验证,它似乎很稳定,不会使我的应用程序池崩溃。
我的连接字符串现在看起来像这样: Driver={Adaptive Server Enterprise};server=fakeservername;port=5050;Database=fakedbname;AuthenticationClient=activedirectory;UserPrincipal=fakeuserprincipal@FAKEDOMAIN.COM;ServerPrincipal=fakeserverprincipal@FAKEDOMAIN.COM;PacketSize=4096;Max Pool尺寸=250;
其中 fakeuserprincipal 是我的应用程序池用于其身份的用户,fakeuserprincipal 是 kerberos spn 中定义的 Sybase 主机 ID。