Solved: Calling application.run for thttpapplicat doesn't return for finally par lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- vangli · 2023-08-24 09:57 Hi, I am running Ubuntu 22.04 with Lazarus version 3.0RC1 and FPC 3.2.2. I am playing around with creating a webserver application for myself. I am doing this for fun and to keep my brain active as a pensioner. The following code is an shortened extract of my code to pinpoint my question. Its a command line application I start in a terminal window. It runs perfectly, and I am able to terminate with Ctrl-C from terminal. I am aware that Application.Run is a blocking call, which in my case is perfect. What I do expect in my confused thinking, is that after pressing Ctrl-C, the application should write the text in the finally section after returning from the Application.Run call. But No. Where am I wrong (I know, it could probably be me??  )? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program aWebServer;  {$mode objfpc}{$H+} uses  {$ifdef UNIX}  cthreads, cmem,  {$endif}  fphttpapp, httpdefs, httproute, sysutils;  begin  try    Application.Port := 8081; // Service port for webserver.    Application.Threaded := true;    Application.Initialize;    Application.Run;  finally    writeln('Ending application!');  end;end. ---------------------------------------------------------------------- Чебурашка · 2023-08-24 11:11 Run must be terminated calling Application.Terminate method. Since the thread where Run is called is blocked inside the Run call, you need to have another thread, that you will use to do the Terminate call. Probably it is enough to create callback for CTRL+C, and call Terminate from it, without creating explicitely an extra thread for that. Something like this should work (I did not test). Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program aWebServer; {$mode objfpc}{$H+} uses  {$ifdef UNIX}  cthreads, cmem,  {$endif}   BaseUnix,   fphttpapp, httpdefs, httproute, sysutils; procedure HandleSigInt(aSignal: LongInt); cdecl;begin  Writeln('Calling terminate after SIGINT');  Application.Terminate();end; begin  if FpSignal(SigInt, @HandleSigInt) = signalhandler(SIG_ERR) then  begin    Writeln('Failed to install signal error: ', fpGetErrno);    Halt(1);  end;   Writeln('Starting application, press CTRL+C to terminate...');   try    Application.Port := 8081; // Service port for webserver.    Application.Threaded := true;    Application.Initialize;    Application.Run;  finally    writeln('Ending application!');  end;end. ---------------------------------------------------------------------- vangli · 2023-08-24 11:35 Thks. I will test this. Your explanation looks logical. I will follow up after testing. Edit after testing: Still not work 100%. However, I certainly catch the Ctrl+C keypress and enter the HandleSigInt procedure. Then it hangs on Application.Terminate statement. Replacing with a Halt() function do terminate, but the finally statement isn't reached then, naturally. It looks like I have to move sigint functionality into the THtppApplication class through a user defined inherited class. Anyway, thks a lot for the help, Чебурашка. I will explore more, and when I found a way update this thread. ---------------------------------------------------------------------- ojz0r · 2023-08-24 12:08 Another option is to include a simple button in the webpage that calls terminate and launch the app as nohup (no hang up). That way the app will run as a daemon and not block the shell. ---------------------------------------------------------------------- Чебурашка · 2023-08-24 12:29 Quote from: vangli on August 24, 2023, 01:35:54 pmThks. I will test this. Your explanation looks logical. I will follow up after testing. Edit after testing: Still not work 100%. However, I certainly catch the Ctrl+C keypress and enter the HandleSigInt procedure. Then it hangs on Application.Terminate statement. Replacing with a Halt() function do terminate, but the finally statement isn't reached then, naturally. It looks like I have to move sigint functionality into the THtppApplication class through a user defined inherited class. Anyway, thks a lot for the help, Чебурашка. I will explore more, and when I found a way update this thread. I checked where I use this class and for me the described approach works, except that I have also Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure HandleSigInt(aSignal: LongInt); cdecl;begin  Writeln('Calling terminate after SIGINT');  Application.Terminate();   while (not Application.Terminated) do Sleep(1); // WAS MISSING, SORRY!!!end;  but I also have to say that I have wrapped the http app into a thread separated by the main thread. And I Terminate the http app like showed before. Maybe this is why it does not work for you. ---------------------------------------------------------------------- vangli · 2023-08-24 12:43 Yes Чебурашка. It look like I has to create a separate thread like you describe. The while statement has no effect. Application.Terminate doesn't work because Application.Run is blocking, I think, in my oversimplified approach. ---------------------------------------------------------------------- vangli · 2023-08-24 19:23 Found a workable way. Basically moved the exit information to the HandleSigInt procedure, and there calling Application.Terminate, which set Application.Terminated to True. Wait for the flag to be set, and then free the hole application Instance. And then write some exit information before Halt, and I am back to command line. Wonder if this method introduce some kind of Memory leakage. Thks Чебурашка for your kind help. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program aWebServer; {$mode objfpc}{$H+} uses  {$ifdef UNIX}  cthreads, cmem,  {$endif}  fphttpapp, httpdefs, httproute, sysutils, BaseUnix;  procedure HandleSigInt(aSignal: LongInt); cdecl;begin  Writeln(LineEnding,'Calling terminate after SIGINT');  Application.Terminate;  while not Application.Terminated do Sleep(10);  Application.FreeInstance;  writeln('Write some information when application ends....');  Halt(0);end;          begin  if FpSignal(SigInt, @HandleSigInt) = signalhandler(SIG_ERR) then  begin  Writeln('Failed to install signal error: ', fpGetErrno);    Halt(1);  end;  Writeln('Starting application, press CTRL+C to terminate...');  try    Application.Port := 8081;    Application.Threaded := true;    Application.Initialize;    Application.Run;  finally    writeln('Error!');  end;end. ---------------------------------------------------------------------- zen010101 · 2024-07-17 18:32 It is a bug mentioned here: https://gitlab.com/freepascal.org/fpc/source/-/issues/36741#original- reporter-info-from-mantis-luca-olivlucareporter-name-luca-olivetti There is an ugly workaround: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure signalHandler(signum: cint); cdecl;begin    Raise Exception.Create('EXIT THE APPLICATION');end;  Everything is working fine, but you might see an exception message pop up, no need to worry about any memory leaks.