Indy 10:
two threads, thread 1 is calling Get on an TIdHTTP and blocked reading data. thread 2 will call disconnect on the same TIdHTTP in order to interrupt the Get.
I'm using Digest Authentication on the TIdHTTP and i get an AV ocassionally.
callstack for thread 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]
callstack for thread 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]
basically at the end of the DoRequest it drops into a disconnect. seems like there's a race condition on the disconnects trying to free Request.Authentication.
downloaded the latest code for Indy 10 and looking at the code i believe the behavior should be the same.
i believe calling disconnect from another thread is the recommended usage pattern, am i wrong? is this a bug in Indy? seems like it would be necessary to lock the disconnect but hard to see what deadlocks that might create. anyone else ran into this?
Yes, what you are encountering is a race condition with both threads trying to free the same Request.Authentication
object twice when the socket is being disconnected. Given the stack traces, both threads would have to be disconnecting the socket at exactly the same time, because Disconnect()
only calls DoOnDisconnect()
if the IOHandler
is still open, and the IOHandler
is closed before DoOnDisconnect()
is called.
What you could try doing is use the OnStatus
event to enter a thread-safe lock such as a critical section or mutex in the hsDisconnecting
state, and leave the lock in the hsDisconnected
state. IOHandler.Close()
and DoOnDisconnect()
are called in between those states, so that would effectively serialize your threads so they cannot disconnect the socket and free the Request.Authentication
object at the exact same time anymore.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With