TIdHttpServer 在 Windows 更新后 Active 设置为 False 时冻结

Posted

技术标签:

【中文标题】TIdHttpServer 在 Windows 更新后 Active 设置为 False 时冻结【英文标题】:TIdHttpServer freezing when Active set to False after Windows Update 【发布时间】:2018-07-16 13:01:20 【问题描述】:

我们有一个 Indy(版本 10.6.1.5235)TIdHttpServer“服务”,多年来一直与 Delphi 2007 一起运行良好。在最近的 Windows 更新(KB4338815 和 KB4338830)之后,我们注意到服务在 TIdHttpServer 设置为 false 时冻结。

我已经包含了创建 TIdHttpServer 的源代码。在我们的服务“停止”处理程序中,我们将 IdHttpServer1.Active 设置为 False,这就是它冻结的地方。 Indy 在尝试关闭 http 连接时似乎挂起。有解决办法吗?

更新一个 根据 Remy Lebeau,我创建了一个最小、完整且可验证的示例。这里是:

procedure TMainForm.Button1Click(Sender: TObject);
begin
  memo1.clear;
  iCall := 0;
  IdHTTPServer1 := TIdHTTPServer.Create;
  IdHTTPServer1.MaxConnections := 10;
  IdHTTPServer1.AutoStartSession := True;
  IdHTTPServer1.SessionState := True;
  IdHTTPServer1.OnCommandGet := IdHTTPServer1CommandGet;
  IdHTTPServer1.KeepAlive := False;
  idHttpServer1.DefaultPort := 80;
  if ReuseSocket.checked then
    IDHTTPSERVER1.ReuseSocket :=  rsTrue;
  IdHTTPServer1.Active := True;
end;


procedure TMainForm.IdHTTPServer1CommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
  iCall := iCall + 1;
  if iCall mod 100 = 0 then
    memo1.lines.add(inttostr(iCall)+ ' calls made');
  AResponseInfo.ContentText := '<html><body>Hello There</body></html';
end;

procedure TMainForm.StopClick(Sender: TObject);
begin
  try
    IdHTTPServer1.Active := False;
    memo1.lines.add('IdHTTPServer1.Active := False;');
  except
    on e: exception do
      memo1.lines.add('Exception on IdHTTPServer1.Active := False; Message:'+e.message);
  end;

end;

应用程序可以正常运行,但是一旦您单击将 IdHttpServer Active 属性设置为 False 的“停止”按钮,它就会挂起。

【问题讨论】:

您可以尝试更新版本的 Indy 吗? (10.6.1 比较老了) 是的。下载了 Indy Version10.6.2.5464 并会让你知道结果。这是 Indy 的最新版本吗?旁注:在 indyproject.org 上有下载的地方吗?我找到了indyproject.org/Sockets/Download/Files/Indy10.EN.aspx,但似乎没有源下载。我终于从indy.fulgan.com得到它了,这是官方下载库吗? indy.fulgan.com 用于夜间快照,但您也可以直接从subversion repository 查看源代码,另请参阅indy.fulgan.com/… @MSchenkel 您没有说在您停用服务器时是否有任何活动的客户端连接。但是,您的 OnCommandGet 事件处理程序不是线程安全的。 TIdHTTPServer 是一个多线程组件,它的事件是在内部工作线程的上下文中触发的,因此在访问 Form 上的 TMemo 组件时必须与主 UI 线程同步,否则会发生坏事。我建议您使用 TThread.Queue()TIdNotify 来完成此操作,这样服务器就不必等待同步完成。 @MSchenkel 如果编写不正确,即使是简单的测试也会导致大问题。永远不要从 UI 线程之外访问 UI 组件。不,TCriticalSection 不会解决这个问题(尽管您可以使用它来提供对您的iCall 变量的安全访问,但至少可以考虑使用TIdThreadSafeInteger)。 Indy 服务器在停用期间会自动为您断开活动客户端。当 Indy 等待这些客户端线程终止时会发生冻结,如果您的事件处理程序导致死锁(并且从 UI 线程之外访问 UI 组件可以死锁),它们将不会终止。 【参考方案1】:

您可能遇到过类似的问题:

Windows 2012 R2 closesocket() hangs on listening socket

该问题是由 Microsoft KB4338815 的补丁带来的,导致 closesocket 在 Intel Xeon 处理器上永远挂起

通过卸载您已安装的 KB4338815 解决了该问题。因此,请尝试在您的系统上卸载该 KB,看看它是否能解决您的问题。

【讨论】:

是的...在我们删除更新后一切正常。 在***.com/questions/51372116/… 中查看我的答案,了解微软的补丁

以上是关于TIdHttpServer 在 Windows 更新后 Active 设置为 False 时冻结的主要内容,如果未能解决你的问题,请参考以下文章

IdHttpServer实现webservice(130篇DataSnap文章)

如何在本地机器上嗅探/侦听 HTTP? [关闭]

如何调用 Delphi 程序来生成 HTML 页面内容

为啥在 Windows 上创建新进程比在 Linux 上更昂贵?

Visual Studio 2015 将目标平台更改为 windows 7

有啥方法可以使 SQLPlus 中的输出更宽(在 Windows 上)?