NpgsqlConnection.Open在Npgsql.ConnectorPool.Allocate()中被阻止调用Monitor.Enter

时间:2016-08-26 13:12:10

标签: c# .net multithreading deadlock npgsql

.NET 5.6.1任务基于并行库的应用程序在NpSql.dll 3.1.6调用 NpgsqlConnection.Open()时停止响应。

经过进一步调查后,似乎100个服务于特定连接字符串的线程正在等待Monitor.Enter信号。等待线程的callstacks与此相同:

[GCFrame: 000000cd8922cec8] 
[GCFrame: 000000cd8922d0f0] 
[HelperMethodFrame: 000000cd8922d128] System.Threading.Monitor.Enter(System.Object)
Npgsql.ConnectorPool.Allocate(Npgsql.NpgsqlConnection, Npgsql.NpgsqlTimeout)
Npgsql.NpgsqlConnection.OpenInternal() 

锁定转储指向孤立锁定问题:MonitorHeld值等于1个所有者+ 546个服务员(1 + 546 * 2 = 1093),锁定所有者线程已死(线程为0)

Index     SyncBlock      MonitorHeld    Owning  Thread    Info       Owner
220427  000000d26dd7b028   1093           1       0        XXX   Npgsql.ConnectorPool

ConnectorPool.Allocate()中的不安全代码块内部没有生成异常,这有助于解释孤立锁。

没有理由相信我们的代码导致线程过早死亡:应用程序中没有任何地方显式调用 Thread.Abort()

此时我们已经没有想法了。 感谢您查看这个。

1 个答案:

答案 0 :(得分:2)

更新

  1. 我们团队成员的错误报告是submitted到npsql。

  2. 在对日志进行更彻底的搜索后,我们发现由于竞争条件,来自NpSql dll 3.1.6版本的ConnectorPool.Allocate()中的单个NullReferenceException实例。查看当前NpSql repo中的ConnectorPool.cs,通过将静态_pruningTimer转换为自3.1.7版以来基于实例的字段来修复此特定问题。

  3. 结论:从NpSql 3.1.6升级到3.1.7解决了ConnectorPool.Allocate()中的死锁问题。