Recent

Author Topic: Detect program exit  (Read 4974 times)

nugax

  • Full Member
  • ***
  • Posts: 232
Detect program exit
« on: March 18, 2018, 11:24:59 pm »
Anyone know how to detect when a program terminates to run code to clean up?
-Nugax

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Re: Detect program exit
« Reply #1 on: March 18, 2018, 11:27:44 pm »
Create finalization section.
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

Thaddy

  • Hero Member
  • *****
  • Posts: 14204
  • Probably until I exterminate Putin.
Re: Detect program exit
« Reply #2 on: March 19, 2018, 10:24:53 am »
Create finalization section.
That only works if you use units. And WHICH unit is finalized first? before true end?
In the case of a single program file you need different means. E.g: pack it in a try finally. Top of finally is program end before releasing resources.
Code: Pascal  [Select][+][-]
  1. program whendoIstartreleasingresources;
  2. begin
  3. try
  4. // your program
  5. finally
  6.   writeln('After this I will release your mess');
  7.  // etc.
  8. end;
  9. end.
« Last Edit: March 19, 2018, 10:29:47 am by Thaddy »
Specialize a type, not a var.

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: Detect program exit
« Reply #3 on: March 19, 2018, 10:29:32 am »
In my old Turbo Pascal days there was something called ExitProc.
O, look, it's still there :D
https://www.freepascal.org/docs-html/rtl/system/exitproc.html

You could assign a procedure to ExitProc which will always run upon exit.
You can also check ExitCode for >0 for any runtime errors.

Using proper try/finally or the correct events (if you use TApplication) is of course preferred.

Thaddy

  • Hero Member
  • *****
  • Posts: 14204
  • Probably until I exterminate Putin.
Re: Detect program exit
« Reply #4 on: March 19, 2018, 10:30:35 am »
 :D :D :D :D True, so true. Just make sure ExitProc is not assigned multiple times...

But I understood the question as: what is the point program functionality ends, but before releasing any assigned resources until the program is totally finished.
ExitProc is called AFTER that.
« Last Edit: March 19, 2018, 10:32:46 am by Thaddy »
Specialize a type, not a var.

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: Detect program exit
« Reply #5 on: March 19, 2018, 10:32:55 am »
Or loop the old value of ExitProc to the next (that's what I did back in the day).

Code: Pascal  [Select][+][-]
  1. var OldExitProc:Pointer;
  2. procedure EindeUse;
  3. var S:String; Ch:Word;
  4.     Regs:Registers;
  5. begin ExitProc:=OldExitProc; { reset the old exitproc }
  6.     { CursorBegin:=0;  CursorEind:=0; } Cursor(On,Ins);
  7.       if ((ExitCode>0) and (ExitCode<256)) or (ErrorAddr<>Nil) then begin
  8.          S:=GetExtendedError(ExitCode);
  9.          S:=IntStr(ExitCode,3)+' - '+S;
  10.          { TextMode(OudeMode); }
  11.  
  12.          Window(1,1,80,AantRegs);
  13.          TextAttr:=LightGray+Black*16;
  14.          ClrScr;
  15.  
  16.          Beep; Beep;
  17.          DrawWindow(14,10,66,13,DoubleFrame,C_N_Window,'',C_N_Tekst);
  18.          GotoXy(16,11); Writeln(S); GotoXy(16,12); Ch:=ReadWord;
  19.       end;
  20.       if ExitCode>255 then ExitCode:=ExitCode-255;
  21. end;
  22.  
  23. begin
  24.       OldExitProc   := ExitProc;
  25.       ExitProc      := @EindeUse;
  26. end.
(O, that's some old code :D)

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: Detect program exit
« Reply #6 on: March 19, 2018, 10:36:11 am »
But I understood the question as: what is the point program functionality ends, but before releasing any assigned resources until the program is totally finished.
ExitProc is called AFTER that.
You mean the program already released resources when ExitProc executes?
If that is the case why would you want to clean up? The program already did that  8-) So there is no need for further clean up.
Anyone know how to detect when a program terminates to run code to clean up?

But I think ExitProc executes before the program has cleaned up anything. So freeing unreleased memory or handles can still be done there.

But like you said, using proper try/finally or the correct events (if you use TApplication) is of course preferred.
« Last Edit: March 19, 2018, 10:38:37 am by rvk »

Fungus

  • Sr. Member
  • ****
  • Posts: 353
Re: Detect program exit
« Reply #7 on: March 19, 2018, 12:13:41 pm »
The accuracy of this post may depend on FPC and kernel-version, but.. Try..finally is not reliable on Linux, SIGKILL (and maybe other SIG's) will not allow the finally block to run. If you want finalization to work reliably on Linux, you must install a SigAction handler (using fpSigAction in unit BaseUnix) to handle termination signals.

https://www.freepascal.org/docs-html-3.0.0/rtl/baseunix/fpsigaction.html
http://man7.org/linux/man-pages/man2/sigaction.2.html

Thaddy

  • Hero Member
  • *****
  • Posts: 14204
  • Probably until I exterminate Putin.
Re: Detect program exit
« Reply #8 on: March 19, 2018, 01:45:22 pm »
SIGKILL is the same as Ctr-C on Windows. If your program is started from a terminal window under windows you can see that behavior.
So this is not a platform issue. KILL is a bail out now. Under Windows, if you kill the process from the process manager a finally block will also not be executed. There are similar ways to mitigate that under windows. And Lazarus has support for that: OnCloseQuery
« Last Edit: March 19, 2018, 01:51:06 pm by Thaddy »
Specialize a type, not a var.

Fungus

  • Sr. Member
  • ****
  • Posts: 353
Re: Detect program exit
« Reply #9 on: March 19, 2018, 03:09:22 pm »
@Thaddy: Sending SIGTERM to a FPC program using command "kill -SIGTERM pid" will cause the finally block not to be reached. I've had quite some trouble with this in a service started and stopped from a SysV style init script and the only sollution was to hook up a handler for SigAction.

Thaddy

  • Hero Member
  • *****
  • Posts: 14204
  • Probably until I exterminate Putin.
Re: Detect program exit
« Reply #10 on: March 19, 2018, 03:35:38 pm »
@Thaddy: Sending SIGTERM to a FPC program using command "kill -SIGTERM pid" will cause the finally block not to be reached. I've had quite some trouble with this in a service started and stopped from a SysV style init script and the only sollution was to hook up a handler for SigAction.
Which is exactly wat OnCloseQuery underneath does. Whith other names, but effect is the same.
Specialize a type, not a var.

Fungus

  • Sr. Member
  • ****
  • Posts: 353
Re: Detect program exit
« Reply #11 on: March 19, 2018, 03:52:00 pm »
A service does not have a GUI, thus no OnCloseQuery. Dunno if TApplication.OnEndSession can be used but a SigAction handler works just fine :)

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: Detect program exit
« Reply #12 on: March 19, 2018, 03:53:12 pm »
You might be right about the signal of SIGTERM that the process is able to do a OnCloseQuery.

But Fungus first mentioned SIGKILL.
Quote
Although SIGKILL is defined in the same signal header file as SIGTERM, it cannot be ignored by the process. In fact, the process isn’t even made aware of the SIGKILL signal since the signal goes straight to the kernel init. At that point, init will stop the process. The process never gets the opportunity to catch the signal and act on it.
https://major.io/2010/03/18/sigterm-vs-sigkill/

So I don't think that the process can do anything with a SIGKILL (because it doesn't even see that).

I even doubt that fpSigAction can "catch" a SIGKILL (but I'm not sure).

Fungus

  • Sr. Member
  • ****
  • Posts: 353
Re: Detect program exit
« Reply #13 on: March 19, 2018, 04:06:53 pm »
I even doubt that fpSigAction can "catch" a SIGKILL (but I'm not sure).

Sorry for the confusion with the mentioning of SIGKILL in my first post. According to specs, SIGKILL and SIGSTOP cannot be trapped: http://man7.org/linux/man-pages/man2/sigaction.2.html

I just recall that I had a hassle figuring out why the finally block was not executed when sending a SIGTERM to a service on Linux. The only sollution I could figure out back them was the SigAction handler :)

 

TinyPortal © 2005-2018