C# Web 服务卡住等待锁定,不返回

发布于 2024-09-05 23:04:59 字数 2665 浏览 3 评论 0原文

我们有一个 C#(2.0) 应用程序,它通过 Web 服务与我们的服务器(在 java 中)通信。

最近,我们开始在(仅)我们的一台实验室机器(XP)中看到以下行为: 偶尔(每隔几天),一个 Web 服务请求会被卡住,不会返回或超时。

以下是它似乎被卡住的堆栈跟踪。

不知道这里发生了什么。 任何指针都会有很大帮助。

ESP EIP
05eceeec 7c90eb94 [GC框架:05eceeec] 05ecefbc 7c90eb94 [HelperMethodFrame_1OBJ: 05ecefbc] System.Threading.Monitor.Enter(System.Object) 05ecf014 7a5b0034 System.Net.ConnectionGroup.Disassociate(System.Net.Connection) 05ecf040 7a5aeaa7 System.Net.Connection.PrepareCloseConnectionSocket(System.Net.ConnectionReturnResult 参考) 05ecf0a4 7a5ac0e1 System.Net.Connection.ReadStartNextRequest(System.Net.WebRequest, System.Net.ConnectionReturnResult ByRef) 05ecf0e8 7a5b1119 System.Net.ConnectStream.CallDone(System.Net.ConnectionReturnResult) 05ecf0fc 7a5b3b5a System.Net.ConnectStream.ReadChunkedSync(字节[],Int32, 整数32) 05ecf114 7a5b2b90 System.Net.ConnectStream.ReadWithoutValidation(字节[],Int32, Int32,布尔值) 05ecf160 7a5b29cc System.Net.ConnectStream.Read(字节[],Int32,Int32) 05ecf1a0 79473cab System.IO.StreamReader.ReadBuffer(Char[], Int32, Int32, 布尔值参考) 05ecf1c4 79473bd6 系统.IO.StreamReader.Read(Char[], Int32, Int32) 05ecf1e8 69c29119 系统.Xml.XmlTextReaderImpl.ReadData() 05ecf1f8 69c2ad70 System.Xml.XmlTextReaderImpl.ParseDocumentContent() 05ecf20c 69c292d7 系统.Xml.XmlTextReaderImpl.Read() 05ecf21c 69c2929d 系统.Xml.XmlTextReader.Read() 05ecf220 6991b3e7 System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(System.Web.Services.Protocols.SoapClientMessage, System.Net.WebResponse、System.IO.Stream、布尔值) 05ecf268 69919ed1 System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(System.String, System.Object[])

编辑:

David的回答后,我再次查看了所有线程,找到了死锁的同谋:

ESP EIP
11a2f6f0 7c90eb94 [GC帧:11a2f6f0] 11a2f7c0 7c90eb94 [HelperMethodFrame_1OBJ: 11a2f7c0] System.Threading.Monitor.Enter(System.Object) 11a2f818 7a5ae107 系统.Net.Connection.CloseOnIdle() 11a2f844 7a5b0403 System.Net.ConnectionGroup.DisableKeepAliveOnConnections() 11a2f878 7a58c035 系统.Net.ServicePoint.ReleaseAllConnectionGroups() 11a2f8b4 7a58d40a System.Net.ServicePointManager.IdleServicePointTimeoutCallback(计时器,Int32,System.Object) 11a2f8e8 7a5d2f40 系统.Net.TimerThread+TimerNode.Fire() 11a2f928 7a5d2bb2 System.Net.TimerThread + TimerQueue.Fire(Int32 ByRef) 11a2f968 7a5d2540 系统.Net.TimerThread.ThreadProc() 11a2f9b4 793d7a7b 系统.Threading.ThreadHelper.ThreadStart_Context(系统.对象) 11a2f9bc 793683dd System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,System.Threading.ContextCallback,System.Object) 11a2f9d4 793d7b5c 系统.Threading.ThreadHelper.ThreadStart() 11a2fbf8 79e88f63 [GCFrame: 11a2fbf8]

那么,我们知道它是否在 4.0 中得到修复吗?

We have a C#(2.0) application which talks to our server(in java) via web services.

Lately we have started seeing following behavior in (ONLY)one of our lab machines(XP):
Once in a while(every few days), one of the webservice request will just get stuck, will not return or timeout.

Following is the stacktrace where it seem to be stuck.

Have no clue what is going on here.
Any pointer would be of great help.

ESP EIP
05eceeec 7c90eb94 [GCFrame: 05eceeec]
05ecefbc 7c90eb94 [HelperMethodFrame_1OBJ: 05ecefbc]
System.Threading.Monitor.Enter(System.Object)
05ecf014 7a5b0034
System.Net.ConnectionGroup.Disassociate(System.Net.Connection)
05ecf040 7a5aeaa7
System.Net.Connection.PrepareCloseConnectionSocket(System.Net.ConnectionReturnResult
ByRef)
05ecf0a4 7a5ac0e1
System.Net.Connection.ReadStartNextRequest(System.Net.WebRequest,
System.Net.ConnectionReturnResult ByRef)
05ecf0e8 7a5b1119
System.Net.ConnectStream.CallDone(System.Net.ConnectionReturnResult)
05ecf0fc 7a5b3b5a System.Net.ConnectStream.ReadChunkedSync(Byte[], Int32,
Int32)
05ecf114 7a5b2b90 System.Net.ConnectStream.ReadWithoutValidation(Byte[], Int32,
Int32, Boolean)
05ecf160 7a5b29cc System.Net.ConnectStream.Read(Byte[], Int32, Int32)
05ecf1a0 79473cab System.IO.StreamReader.ReadBuffer(Char[], Int32, Int32,
Boolean ByRef)
05ecf1c4 79473bd6 System.IO.StreamReader.Read(Char[], Int32, Int32)
05ecf1e8 69c29119 System.Xml.XmlTextReaderImpl.ReadData()
05ecf1f8 69c2ad70 System.Xml.XmlTextReaderImpl.ParseDocumentContent()
05ecf20c 69c292d7 System.Xml.XmlTextReaderImpl.Read()
05ecf21c 69c2929d System.Xml.XmlTextReader.Read()
05ecf220 6991b3e7
System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(System.Web.Services.Protocols.SoapClientMessage,
System.Net.WebResponse, System.IO.Stream, Boolean)
05ecf268 69919ed1
System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(System.String,
System.Object[])

Edit:

After David's Answer, i saw all the threads again and found the accomplice for the deadlock:

ESP EIP
11a2f6f0 7c90eb94 [GCFrame: 11a2f6f0]
11a2f7c0 7c90eb94 [HelperMethodFrame_1OBJ: 11a2f7c0] System.Threading.Monitor.Enter(System.Object)
11a2f818 7a5ae107 System.Net.Connection.CloseOnIdle()
11a2f844 7a5b0403 System.Net.ConnectionGroup.DisableKeepAliveOnConnections()
11a2f878 7a58c035 System.Net.ServicePoint.ReleaseAllConnectionGroups()
11a2f8b4 7a58d40a System.Net.ServicePointManager.IdleServicePointTimeoutCallback(Timer, Int32, System.Object)
11a2f8e8 7a5d2f40 System.Net.TimerThread+TimerNode.Fire()
11a2f928 7a5d2bb2 System.Net.TimerThread+TimerQueue.Fire(Int32 ByRef)
11a2f968 7a5d2540 System.Net.TimerThread.ThreadProc()
11a2f9b4 793d7a7b System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
11a2f9bc 793683dd System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
11a2f9d4 793d7b5c System.Threading.ThreadHelper.ThreadStart()
11a2fbf8 79e88f63 [GCFrame: 11a2fbf8]

So, do we know if it is fixed in 4.0?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

早乙女 2024-09-12 23:04:59

这看起来相关... CLR 中的错​​误?
Microsoft Connect

编辑:4.0框架中的代码看起来锁的处理方式完全不同。它可能已经修复了该错误。

This looks related... bug in CLR?
Microsoft Connect

Edit: the code in the 4.0 framework looks like locks are handled totally differently. It may have fixed the bug.

话少心凉 2024-09-12 23:04:59

几乎可以肯定你遇到了僵局。假设线程 A 取出对象 2 上的锁,然后等待对象 1 解锁。线程 A 必须等待,因为线程 B 在解锁对象 2 之前已取出对象 1 上的锁。现在线程 A 和线程 B 都将永远等待,因为每个线程都在等待对方解锁某些内容。

使用调试器查看程序中的每个线程,看看哪两个线程都在那里等待锁定。然后找出他们正在等待哪些锁。然后弄清楚如何重写程序,以便永远不会以两个线程上不一致的顺序取出这两个锁。

请记住,编写正确的锁定代码需要了解程序中所有锁的全局知识,以及所有线程上可能以每种可能的顺序取出锁的操作的全局知识。这就是为什么很难做到正确的原因;大多数编程任务只需要本地知识。锁需要整个程序的全局知识,包括您没有编写的部分。如果某个第三方 dll 正在获取某个对象上的锁,并且您的代码正在等待同一对象,则您必须就正确的锁排序选择与该第三方代码达成一致。

这是最有可能的原因。还有一个不太可能但可能的其他原因,即有时您会在锁被取出和执行解锁finally块之间中​​止线程。这会导致 C# 3 及以下版本出现死锁;我们修复了 C# 4 中的代码生成器,这样就不会再发生这种情况。不过,这里的故事的寓意不是“使用 C# 4”,而是“永远不要中止线程,特别是不要中止可能锁定某些内容的线程”。无论如何,当您要关闭进程时,线程中止只能作为最后的手段。

You almost certainly have a deadlock. Suppose you have thread A which takes out the lock on object 2 and then waits for object 1 to be unlocked. Thread A has to wait because thread B has taken out the lock on object 1 before it unlocks object 2. Now thread A and thread B will both wait forever because each is waiting on the other to unlock something.

Use the debugger to look at every thread in your program and see which two threads are both sitting there waiting for a lock. Then figure out which locks they are waiting for. Then figure out how to rewrite your program so that those two locks are never taken out in an order which is inconsistent on two threads.

Remember, writing correct locking code requires global knowledge of all locks in the program, all operations on all threads that could possibly take them out in every possible ordering. That's why it's so hard to get it right; most programming tasks require only local knowledge. Locks require global knowledge of the entire program, including the parts that you didn't write. If some third party dll is taking out a lock on an object and your code is waiting on the same object, you have to agree with that third party code on what the correct lock ordering choice is.

That's the most likely cause. There is an unlikely but possible other cause, which is that sometimes you abort a thread between when the lock is taken out and the unlocking finally block is executed. That will cause a deadlock in C# 3 and below; we've fixed the code generator in C# 4 so that this no longer happens. The moral of the story here though is not "use C# 4", it's "don't abort a thread, ever, and particularly don't abort a thread that might be locking on something". Thread aborts should be only used as a last resort, when you are taking down the process anyway.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文