Indy TCP服务器在停用时冻结

3
我有一个基于Indy的服务器TIdTCPServer,该服务器有三个绑定不同端口的端口。如果我将客户端连接到这三个端口,然后停用服务器,它似乎陷入了死锁状态。无论我做什么,它都不会响应我的点击,甚至不会向Windows报告“未响应”。如果在停用服务器之前断开客户端连接,一切都很完美。我指的是“停用” Server.Active:= False;
有人遇到过这种情况吗?可能是什么原因呢?我这里没有任何跨越线程的操作,可能导致死锁(例如GUI更新)。我尝试使用Antifreeze组件 TIdAntiFreeze ,但没有好运气。

如果没有连接会发生什么?它是否能正确停用?如果可以,请在停用服务器之前从客户端终止连接。 - Shaun07776
是的,如果没有更多的客户端连接,它会成功地停用。 - Jerry Dodge
2
TIdTCPServer的“Active”属性设置器会自动断开任何活动客户端连接。但它还必须等待这些线程终止,这就是这种死锁发生的地方,如果这些线程没有正确终止,通常是由于事件处理程序代码中的用户错误。我们需要查看Jerry的实际代码。 - Remy Lebeau
谢谢@Remy,我正在阅读您在Indy的TIdCustomTCPServer.TerminateAllThreads中的评论...除非“RLebeau”是其他人? :P 证明您确实知道自己在说什么 - Jerry Dodge
3
是的,那是我。我在Indy开发团队中。 - Remy Lebeau
2个回答

4

TIdTCPServer是一个多线程组件。在服务器停用期间发生死锁意味着其中一个或多个客户端线程没有正确终止。通常情况下,这意味着您的服务器事件处理程序正在执行一些不应该执行的操作,通常要么是捕获并丢弃Indy的内部异常,使其与忙于终止服务器的线程上下文同步,要么在Indy外部某些其他地方发生死锁。如果没有看到您的实际代码,就无法确定究竟是哪种情况,但总是由用户错误引起这种死锁。

TIdAntiFreeze仅影响在主线程上下文中运行的Indy组件。TIdTCPServer不受影响。


明白了,没有看到我的代码就无法确定问题所在,我仍在寻找问题的原因。这至少帮助我理解应该在哪里寻找。 - Jerry Dodge
我找到了源代码,它是一个我一直在追踪的内存泄漏问题。一旦修复了这个泄漏问题,这个问题也得到了解决。这个内存泄漏问题出现在其中一个客户端线程中。 - Jerry Dodge

1
I added this code on Form.OnClose works good!

procedure TformSFTP.FormClose(Sender: TObject; var Action: TCloseAction);
var
  iA : Integer;
  Context: TidContext;
begin
 if sftpServidorFTP.Active then
     with sftpServidorFTP.Contexts.LockList do
        try
           for iA := Count - 1 downto 0 do
           begin
              Context := Items[iA];
              if Context = nil then
                 Continue;
              Context.Connection.IOHandler.WriteBufferClear;
              Context.Connection.IOHandler.InputBuffer.Clear;
              Context.Connection.IOHandler.Close;
              if Context.Connection.Connected then
                 Context.Connection.Disconnect;
           end;
        finally
           sftpServidorFTP.Contexts.UnlockList;
        end;

If the sftpServidorFTP is active:

sftpServidorFTP.Active := False;

End.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接