开发者

Deadlock on tidtcpserver.active = false (Delphi2007/indy10)

开发者 https://www.devze.com 2023-01-09 11:49 出处:网络
I am having a problem with some code that was written by a developer that has now left our company, the code implements a tcpserver that responds to an XML based protocol. This appears to be working a

I am having a problem with some code that was written by a developer that has now left our company, the code implements a tcpserver that responds to an XML based protocol. This appears to be working absolutely fine in our test environment but one or two customers are having problems with application shutdown.

I have traced this to what appears to be a deadlock when tidtcpserver.active = false is called. I am already aware that a deadlock can be caused by one of the connection treads making a synchronised call to the main thread, whilst the main thread is waiting for the connection threads to terminate.

I am already using a tidthreadsafestringlist to pass the data to the main thread for processing, and wh开发者_运维知识库ere I need to call a procedure from the main thread I have created a tidnotify descendant to do this. can anyone think of anything else to look for.


I had already been checking the exception handling,

this is what i have in the onexecute event

try
  // code to handle connection including tidnotify etc....
except
  on E:Exception do
  begin
    if (e.InheritsFrom(EIdSilentException) = False) then
      TXMLTraceNotify.XMLTrace('TCPServerExecute: ' + E.Message,ttProblem, FTraceProc);
    raise; //we must raise all exceptions for indy to handle them.
  end;

end;


Here is how i'm using the TS-stringlist

Declaration.

public
  TransactionStrings: TIdThreadSafeStringList;

its created in the constructor and destroyed in the destructor.

this is how i'm adding to it in the context of the tcpserver.

  TransactionStrings.Add(newTrans.AsString);

And this is how i'm reading from it in the context of the main application thread

slXMLTrans := TStringList.Create;
try
  slTemp := FCustomXMLServer.TransactionStrings.Lock;
  try
    slXMLTrans.Assign(slTemp);
    slTemp.Clear;
  finally
    FCustomXMLServer.TransactionStrings.Unlock;
  end;

  if slXMLTrans.Count > 0 then
  begin
    for i := 0 to Pred(slXMLTrans.Count) do
      TAbstractTerminal.ProcessXMLTrans(slXMLTrans[i]);
    slXMLTrans.Clear;
  end;
finally
  slXMLTrans.Free;
end;

I think this is the correct way to use it but I await your comments.


Deadlocks when setting the Active property to False are a classic, and often discussed, issue when using TIdTCPServer incorrectly. The only way the server deadlocks is when the connection threads do not terminate correctly. That MAY be caused by synchronizing operaton to the main thread while the main thread is busy deactivating the server, in which case the use of TIdNotify would does eliminate any such deadlock conditions.

However, that is not the only way to prevent a connection thread from terminating. Another possibility is if your server event handlers have exception handling in them that is blocking Indy's internal notifications from being processed. That can cause runaway threads that keep running but never know that they need to stop. If you are catching exceptions in your code, make sure you re-throw any EIdException-derived exceptions and let the server handle them internally.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号