Forum > Linux

At power down ?

<< < (2/5) > >>

Thaddy:
I was referring to both Lazarus and Delphi.
I can write you an example if you want.
Come to think of it: OnCloseQuery in the main form can be used in the same fashion.
It is the only place where you can do some work *just* before shutdown, like closing sockets, rotating logs, thread clean-up etc..
That examples are old does not matter as long as they are good.
That it is little used by amateurs (not that I would call you that) is simply lack of knowledge.
That's what you get with screendrawers pretending to program.
The same scheme is used in many other programming languages. In Windows it is even part of the API as it is in UNIX, I believe. (but be careful with SIGKILL which does not obey clean shutdown, just like halt() )

This only works on a real restart or shutdown although formclosequery also works on a simple application shutdown.

Example that writes the time of last system shutdown in a caption:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit query; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs; type   { TForm1 }   TForm1 = class(TForm)    procedure FormCreate(Sender: TObject);  private   public     procedure QueryEndSession(var cancel:Boolean);  end; var  Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.FormCreate(Sender: TObject);var  f:text;  s:string;begin  Application.OnQueryEndSession := @QueryEndSession;  if FileExists('laststart.txt') then  begin    System.assign(f,'laststart.txt');    reset(f);    readln(f,s);    form1.caption := s;    System.Close(f);  end;end; procedure TForm1.QueryEndSession(var cancel: Boolean);var  f:text;begin // here you make sure all clean-ups are done. // threads, sockets, you name it. // better not use GUI elements here...these block.  cancel  := true;  system.Assign(f,'laststart.txt');  rewrite(f);  writeln(f, DateTimeToStr(Now));  system.close(f);  cancel := false;end; end.You have to run the application at least twice and with a real system restart to see the result.
You can cancel during the restart, the file will be written.

dbannon:
Yep, that works absolutely as I (and, importantly, my end users) expect.

In my test app, I dropped an Application component on the form, your model of using Application is neater and I tested my real app using that. In both cases, it works perfectly!

I have had a good look at how it works and I conclude that while FormCloseQuery() is called during a powerdown event, it is not able to delay the SigKILL (or maybe just power going off) for any more that 20mS or so.  On the other hand, TApplication.OnQueryEndSession can insist on its 90 second delay if necessary.

As this is an important behaviour, I'll make some notes on the wiki.

Thanks Thaddy, I am very glad to finally understand this issue.

Davo

Thaddy:
But mark the difference:
https://linuxhandbook.com/sigterm-vs-sigkill/

dbannon:

--- Quote from: Thaddy on September 12, 2025, 07:34:03 am ---But mark the difference:
https://linuxhandbook.com/sigterm-vs-sigkill/

--- End quote ---

Oh,  should definitely never be confused, by either the programmer or the user/sysAmin. I taught my SysAdmin staff to use SigTERM if necessary but if that fails, think very carefully before using SigKILL. My (evolving) code redirects SigTERM to my own handler that calls FormClose. Thats fine if its from, eg, the kill command which send SigTerm by default. Its not adequate if its a powerdown. So far, it appears Application.OnQueryEndSession takes precedence over FPSignal(). So, my writeup (subject to revision) will state you need to handle at least four different scenarios -

* User initiated close with the Window Decoration close button which ends up in FormCloseQuery();
* User initiated close from a menu, button etc, call close and it ends up in FormCloseQuery();
* A PowerDown event, LCL apps needs to be caught in Application.OnQueryEndSession. In CLI, by a handler redirected to by FPSignal()
* App getting a SigTERM (but NOT at powerdown), caught in a handler redirected to by FPSignal().

I have not addressed HUP, fpc/LCL apps, out of the box, exit immediately on HUP same as TERM. That surprise me, there is a convention that HUP means a re-initialize but not exit, typically reread config etc.

And I prefer to use FPSignal() rather than  FPSigAction(), FPSignal() is marked as depreciated in source but probably by mistake. The C equivalent, signal() is depreciated because it depends on existence (or otherwise) of a macro. FPSignal() has no such dependency and is a useful wrapper round (an awkward) FPSigAction().

There could be a paper in this you know ....

Davo
 

Thaddy:
To add  to the confusion the kill command calls SIGTERM unless SIGKILL is explicitly specified ;)

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version