* Merging revisions r45723 from trunk:

------------------------------------------------------------------------
    r45723 | ondrej | 2020-07-03 19:27:17 +0200 (Fri, 03 Jul 2020) | 1 line
    
    fphttpserver: gracefully close open connections at server destroy
    ------------------------------------------------------------------------

git-svn-id: branches/fixes_3_2@46591 -
This commit is contained in:
michael 2020-08-23 09:21:19 +00:00
parent c15536afdf
commit d2dfbdcac4

View File

@ -88,8 +88,10 @@ Type
TFPHTTPConnectionThread = Class(TThread) TFPHTTPConnectionThread = Class(TThread)
private private
FConnection: TFPHTTPConnection; FConnection: TFPHTTPConnection;
FThreadList: TThreadList;
Public Public
Constructor CreateConnection(AConnection : TFPHTTPConnection); virtual; Constructor CreateConnection(AConnection : TFPHTTPConnection); virtual;
Constructor CreateConnection(AConnection : TFPHTTPConnection; AThreadList: TThreadList);
Procedure Execute; override; Procedure Execute; override;
Property Connection : TFPHTTPConnection Read FConnection; Property Connection : TFPHTTPConnection Read FConnection;
end; end;
@ -121,6 +123,7 @@ Type
FServerBanner: string; FServerBanner: string;
FLookupHostNames, FLookupHostNames,
FThreaded: Boolean; FThreaded: Boolean;
FConnectionThreadList: TThreadList;
FConnectionCount : Integer; FConnectionCount : Integer;
FUseSSL: Boolean; FUseSSL: Boolean;
procedure DoCreateClientHandler(Sender: TObject; out AHandler: TSocketHandler); procedure DoCreateClientHandler(Sender: TObject; out AHandler: TSocketHandler);
@ -137,7 +140,7 @@ Type
procedure SetQueueSize(const AValue: Word); procedure SetQueueSize(const AValue: Word);
procedure SetThreaded(const AValue: Boolean); procedure SetThreaded(const AValue: Boolean);
procedure SetupSocket; procedure SetupSocket;
procedure WaitForRequests; procedure WaitForRequests(MaxAttempts: Integer = 10);
Protected Protected
// Override this to create descendent // Override this to create descendent
function CreateSSLSocketHandler: TSocketHandler; function CreateSSLSocketHandler: TSocketHandler;
@ -648,6 +651,14 @@ begin
Inherited Create(False); Inherited Create(False);
end; end;
constructor TFPHTTPConnectionThread.CreateConnection(AConnection: TFPHTTPConnection; AThreadList: TThreadList);
begin
FThreadList := AThreadList;
if Assigned(FThreadList) then
FThreadList.Add(Self);
CreateConnection(AConnection);
end;
procedure TFPHTTPConnectionThread.Execute; procedure TFPHTTPConnectionThread.Execute;
begin begin
try try
@ -655,6 +666,8 @@ begin
FConnection.HandleRequest; FConnection.HandleRequest;
finally finally
FreeAndNil(FConnection); FreeAndNil(FConnection);
if Assigned(FThreadList) then
FThreadList.Remove(Self);
end; end;
except except
// Silently ignore errors. // Silently ignore errors.
@ -780,6 +793,8 @@ begin
if FThreaded=AValue then exit; if FThreaded=AValue then exit;
CheckInactive; CheckInactive;
FThreaded:=AValue; FThreaded:=AValue;
if FThreaded and not Assigned(FConnectionThreadList) then
FConnectionThreadList:=TThreadList.Create;
end; end;
function TFPCustomHttpServer.CreateRequest: TFPHTTPConnectionRequest; function TFPCustomHttpServer.CreateRequest: TFPHTTPConnectionRequest;
@ -811,7 +826,7 @@ end;
function TFPCustomHttpServer.CreateConnectionThread(Conn: TFPHTTPConnection function TFPCustomHttpServer.CreateConnectionThread(Conn: TFPHTTPConnection
): TFPHTTPConnectionThread; ): TFPHTTPConnectionThread;
begin begin
Result:=TFPHTTPConnectionThread.CreateConnection(Conn); Result:=TFPHTTPConnectionThread.CreateConnection(Conn, FConnectionThreadList);
end; end;
procedure TFPCustomHttpServer.CheckInactive; procedure TFPCustomHttpServer.CheckInactive;
@ -893,7 +908,7 @@ begin
FCertificateData:=CreateCertificateData; FCertificateData:=CreateCertificateData;
end; end;
procedure TFPCustomHttpServer.WaitForRequests; procedure TFPCustomHttpServer.WaitForRequests(MaxAttempts: Integer);
Var Var
FLastCount,ACount : Integer; FLastCount,ACount : Integer;
@ -901,7 +916,7 @@ Var
begin begin
ACount:=0; ACount:=0;
FLastCount:=FConnectionCount; FLastCount:=FConnectionCount;
While (FConnectionCount>0) and (ACount<10) do While (FConnectionCount>0) and (ACount<MaxAttempts) do
begin begin
Sleep(100); Sleep(100);
if (FConnectionCount=FLastCount) then if (FConnectionCount=FLastCount) then
@ -957,10 +972,27 @@ begin
end; end;
destructor TFPCustomHttpServer.Destroy; destructor TFPCustomHttpServer.Destroy;
var
ThreadList: TList;
I: Integer;
begin begin
Active:=False; Active:=False;
if Threaded and (FConnectionCount>0) then if Threaded and (FConnectionCount>0) then
begin
// first wait for open requests to finish and get closed automatically
WaitForRequests; WaitForRequests;
// force close open sockets
ThreadList:=FConnectionThreadList.LockList;
try
for I:= ThreadList.Count-1 downto 0 do
CloseSocket(TFPHTTPConnectionThread(ThreadList[I]).Connection.Socket.Handle);
finally
FConnectionThreadList.UnlockList;
end;
// all requests must be destroyed - wait infinitely
WaitForRequests(High(Integer));
end;
FreeAndNil(FConnectionThreadList);
FreeAndNil(FCertificateData); FreeAndNil(FCertificateData);
inherited Destroy; inherited Destroy;
end; end;