Я устанавливаю веб-сервер с 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;