Recent

Author Topic: [SOLVED] Proper way to terminate embedded TFPHTTPServer in Win  (Read 969 times)

alpine

  • Hero Member
  • *****
  • Posts: 1315
I'm playing with fphttpserver and wrote a test project following (loosely) that document:
https://www.freepascal.org/~michael/articles/webserver1/webserver1.pdf

What I've noticed is that TThread.DoTerminate doesn't get called when you terminate thread in Windows.

But the way the embedded server was outlined into the Michael's document:
Code: Pascal  [Select][+][-]
  1. procedure THTTPServerThread.Execute;
  2. begin
  3.   try
  4.     FServer.Active := True;
  5.   finally
  6.     FServer.Free;
  7.   end;
  8. end;
  9.  
  10. procedure THTTPServerThread.DoTerminate;
  11. begin
  12.   inherited DoTerminate;
  13.   FServer.Active := False;
  14. end;

Since obviously TFPHTTPServer.Active:=True is blocking and TThread.DoTerminate isn't called, anyone have an idea how to terminate the server in a graceful way?

Edit: As a matter of fact TThread.DoTerminate was not executed in Linux either.

It seems that the Michael's example have an issue - FServer.Free won't get executed into the finally clause. Confirmed with heaptrc.

In that case the question becomes even more important. I guess it can be rephrased into: Does anyone know if it is safe to call :
Code: Pascal  [Select][+][-]
  1. TFPHTTPServer.Active:=False
from another thread?


« Last Edit: April 29, 2024, 10:32:00 am by alpine »
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

zamronypj

  • Full Member
  • ***
  • Posts: 139
    • Fano Framework, Free Pascal web application framework
Re: Proper way to terminate embedded TFPHTTPServer in Win
« Reply #1 on: April 28, 2024, 01:25:23 am »
 TFPHTTPServer indirectly uses TSocketServer https://gitlab.com/freepascal.org/fpc/source/-/blob/main/packages/fcl-net/src/ssockets.pp?ref_type=heads. Calling

Code: Pascal  [Select][+][-]
  1. TFPHTTPServer.Active:= true;

Will indirectly, call startAccepting() method of TSocketServer which will run in two nested loops. So it blocks current thread.

Code: Pascal  [Select][+][-]
  1. TFPHTTPServer.Active:= false;
will set fAccepting to false and only works if it calls from other thread. This call alone is not enough to break inner loop. Inner loop exits if there is connection to server and outer loop exists if fAccepting is false.

Code: Pascal  [Select][+][-]
  1. TFPHTTPServer.Active:= false;
  2. TInetSocket.create(your_server_host, your_server_port).free();
  3.  

For example, see FakeConnect() call in TCustomHTTPApplication.Terminate
https://gitlab.com/freepascal.org/fpc/source/-/blob/main/packages/fcl-web/src/base/custhttpapp.pp?ref_type=heads
« Last Edit: April 28, 2024, 01:30:47 am by zamronypj »
Fano Framework, Free Pascal web application framework https://fanoframework.github.io
Apache module executes Pascal program like scripting language https://zamronypj.github.io/mod_pascal/
Github https://github.com/zamronypj

alpine

  • Hero Member
  • *****
  • Posts: 1315
Re: Proper way to terminate embedded TFPHTTPServer in Win
« Reply #2 on: April 29, 2024, 10:31:15 am »
For example, see FakeConnect() call in TCustomHTTPApplication.Terminate
https://gitlab.com/freepascal.org/fpc/source/-/blob/main/packages/fcl-web/src/base/custhttpapp.pp?ref_type=heads

Thank you for that information. As I understand, that fake connection breaks the TSocketServer inner loop to reach FAccepting check in the outer one.

I've noticed some other conditions in TSocketServer.StartAccepting as NonBlocking, AcceptIdleTimeout, OnIdle can clear the Accepting, etc. Too bad that fcl-web, fcl-net are not so well documented and they must to be investigated thoroughly in code :( It has its potential and much more sophisticated than it can be seen at the first look. Thanks again!
« Last Edit: April 29, 2024, 01:09:32 pm by alpine »
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

 

TinyPortal © 2005-2018