5

印地 10:

两个线程,线程 1 在 TIdHTTP 上调用 Get 并阻止读取数据。线程 2 将在同一个 TIdHTTP 上调用 disconnect 以中断 Get。

我在 TIdHTTP 上使用 Digest Authentication,我偶尔会得到一个 AV。

线程 1 的调用栈:

40491D [system.pas][System][@ClassDestroy][8989]
69EF2B [..\..\common\IdAuthenticationDigest.pas][IdAuthenticationDigest][TIdDigestAuthentication.Destroy][109]
404567 [system.pas][System][TObject.Free][8313]
6A2B69 [..\..\Common\IdHTTP.pas][IdHTTP][TIdCustomHTTP.DoOnDisconnected][1587]
534574 [IdTCPConnection.pas][IdTCPConnection][TIdTCPConnection.Disconnect][532]
534B3B [IdTCPConnection.pas][IdTCPConnection][TIdTCPConnection.Disconnect][767]
6A3FB3 [..\..\Common\IdHTTP.pas][IdHTTP][TIdCustomHTTP.DoRequest][2101]

线程 2 的调用堆栈:

402BA3 [system.pas][System][@FreeMem][2477]
404521 [system.pas][System][TObject.FreeInstance][8294]
40491D [system.pas][System][@ClassDestroy][8989]
69EF2B [..\..\common\IdAuthenticationDigest.pas][IdAuthenticationDigest]        [TIdDigestAuthentication.Destroy][109]
404567 [system.pas][System][TObject.Free][8313]
6A2B69 [..\..\Common\IdHTTP.pas][IdHTTP][TIdCustomHTTP.DoOnDisconnected][1587]
534574 [IdTCPConnection.pas][IdTCPConnection][TIdTCPConnection.Disconnect][532]
534B3B [IdTCPConnection.pas][IdTCPConnection][TIdTCPConnection.Disconnect][767]

基本上在 DoRequest 结束时它会断开连接。似乎在尝试释放 Request.Authentication 的断开连接上存在竞争条件。

下载了 Indy 10 的最新代码并查看了我认为行为应该相同的代码。

我相信从另一个线程调用断开连接是推荐的使用模式,我错了吗?这是印地的一个错误吗?似乎有必要锁定断开连接,但很难看到可能会产生什么死锁。还有其他人遇到这个吗?

4

1 回答 1

6

是的,您遇到的是一种竞争条件,Request.Authentication当套接字断开连接时,两个线程都试图释放同一个对象两次。给定堆栈跟踪,两个线程必须同时断开套接字,因为只有在仍然打开Disconnect()时才调用,并且在调用之前关闭。DoOnDisconnect()IOHandlerIOHandlerDoOnDisconnect()

您可以尝试做的是使用该OnStatus事件进入状态中的临界区或互斥锁等线程安全锁hsDisconnecting,并将锁留在hsDisconnected状态中。 IOHandler.Close()DoOnDisconnect()在这些状态之间被调用,这样可以有效地序列化你的线程,这样它们就不能再同时断开套接字并释放Request.Authentication对象了。

于 2012-09-20T19:05:17.440 回答