断开连接时出现IdHTTP访问冲突

时间:2012-09-20 18:04:02

标签: delphi authentication indy disconnect idhttp

Indy 10:

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

我在TIdHTTP上使用摘要式身份验证,我偶尔会得到一个AV。

线程1的callstack:

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的callstack:

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的最新代码并查看了我认为行为应该相同的代码。

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

1 个答案:

答案 0 :(得分:6)

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

您可以尝试做的是使用OnStatus事件进入线程安全锁定,例如hsDisconnecting状态的关键部分或互斥锁,并将锁定保留在{{1}国家。在这些状态之间调用hsDisconnectedIOHandler.Close(),这样就可以有效地序列化线程,这样它们就不能断开套接字并在同一时间释放DoOnDisconnect()对象。