简体   繁体   English

tidtcpserver.active上的死锁= false(Delphi2007 / indy10)

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

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. 我遇到了由已经离开我们公司的开发人员编写的某些代码的问题,该代码实现了一个tcpserver,该tcpserver响应基于XML的协议。 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. 我追踪到当调用tidtcpserver.active = false时似乎出现了死锁。 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 where I need to call a procedure from the main thread I have created a tidnotify descendant to do this. 我已经在使用tidthreadsafestringlist将数据传递到主线程进行处理,并且需要从主线程调用过程,所以我创建了一个tidnotify后代来执行此操作。 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 这是我在onexecute事件中所拥有的

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 这是我使用TS字符串列表的方式

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. 这就是我在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. 当将Active属性设置为False时,死锁是一个不正确使用TIdTCPServer的经典问题,并且经常被讨论。 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. 这可能是由于在主线程忙于停用服务器时将操作数同步到主线程引起的,在这种情况下,使用TIdNotify确实可以消除任何此类死锁情况。

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. 另一种可能性是,如果您的服务器事件处理程序中包含异常处理,从而阻止了Indy的内部通知被处理。 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. 如果您在代码中捕获异常,请确保重新抛出任何EIdException派生的异常,并让服务器在内部对其进行处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM