TIdHTTPServer с TIdServerIOHandlerSSLOpenSSL не возвращается, когда Active установлен на FALSE в консоли Debian - PullRequest
1 голос
/ 05 апреля 2019

Я устанавливаю веб-сервер с Indy и Delphi 10.3.1 в консольном приложении, запущенном в Debian. Я не могу аккуратно завершить работу сервера, установив IdHTTPServer.Active в FALSE, потому что он никогда не вернется, и единственный способ закрыть приложение - это нажать ctrl-c или завершить процесс. Я проверил это в Windows, и все в порядке, поэтому я думаю, что проблема Indy с Linux.

program SrvDemo;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  SysUtils,
  IdContext,
  IdSSL,
  IdCustomHTTPServer,
  IdHTTPServer,
  IdSSLOpenSSL,
  IdServerIOHandler,
  Posix.Base,
  Posix.Fcntl;

var
  CERT_PATH: string;
  HTTPServer: TIdHTTPServer;
  ServerIOHandlerSSLOpenSSL: TIdServerIOHandlerSSLOpenSSL;
begin
  CERT_PATH:='/opt/test_certs/';
  HTTPServer := TIdHTTPServer.Create;
  ServerIOHandlerSSLOpenSSL:=TIdServerIOHandlerSSLOpenSSL.Create;
  try
    HTTPServer.DefaultPort := 4123;
    ServerIOHandlerSSLOpenSSL.SSLOptions.CertFile:=CERT_PATH+'server.crt';
    ServerIOHandlerSSLOpenSSL.SSLOptions.KeyFile:=CERT_PATH+'server.key';

    HTTPServer.IOHandler:=ServerIOHandlerSSLOpenSSL;
    HTTPServer.Active := True;

    Writeln('Server ON - Press any key to stop ...');
    Readln;
    Writeln('Passed ...');
  finally
    Writeln('Passed ...');
    HTTPServer.Active := False;       // --> it hang here
    Writeln('Never passed ...');    
    ServerIOHandlerSSLOpenSSL.Free;   // --> never passed 
    HTTPServer.Free;                  // --> never passed
  end;

  Writeln('Server OFF');              // --> never passed

end.

Я попытался отладить и заметил, что проблема возникает только с SSL и TIdServerIOHandlerSSLOpenSSL, и если я ставлю точку останова в строке LListener.WaitFor ( процедура TIdCustomTCPServer.StopListening из IdCustomTCPServer.pas *) соединение закрывается изящно, возможно, из-за времени для повторного запуска программы достаточно, чтобы позволить ему закрыть соединение. Если я не поставлю точку останова, там будет блокировка программы.


//APR-011207: for safe-close Ex: SQL Server ShutDown 1) stop listen 2) wait until all clients go out
procedure TIdCustomTCPServer.StopListening;
var
  LListenerThreads: TIdListenerList;
  LListener: TIdListenerThread;
begin
  LListenerThreads := FListenerThreads.LockList;
  try
    while LListenerThreads.Count > 0 do begin
      LListener := {$IFDEF HAS_GENERICS_TThreadList}LListenerThreads[0]{$ELSE}TIdListenerThread(LListenerThreads[0]){$ENDIF};
      // Stop listening
      LListener.Terminate;
      LListener.Binding.CloseSocket;
      // Tear down Listener thread
      LListener.WaitFor;   //  --> BREAKPOINT HERE
      LListener.Free;
      LListenerThreads.Delete(0); // RLebeau 2/17/2006
    end;
  finally
    FListenerThreads.UnlockList;
  end;
end;

...