Forum > Linux

At power down ?

(1/5) > >>

dbannon:
I'd really like some help here.

Attached is a demo of a problem with LCL apps running when the Linux box powers down.  It creates 6 extra, non-modal windows keeping track of them in an array. When the main window closes down, it iterates over that array, closing each. (And, possibly, doing something specific because it's app is closing).

However, logging this as it happens reveals two separate actions -

[x] Initially, one or more slave windows usually, somehow, get a close down signal. That is seen in the log in .FormCloseQuery() and .FormClose().
[x] Seven seconds later, a SIGTERM (ie #15) is received by the main window and each one,      including any 'closed' in the above step, are nicely closed and freed.

It appears that the slave Windows 'closed' in stage 1 remain responsive, is perhaps set to not visible (or are disconnected from the XServer (or Wayland)  in much the same was as xkill works). So, it is still usable but has told the world its not.

I can not find any way to determine where this first, bogus 'close' command comes from. Nor any way to tell the difference between it and eg a user initiated close.

And the app holds up the OS shutdown by that seven seconds. If the slave window's CloseAction is set to caFree the window would be gone before a proper shutdown can be performed. Extract from log file (hh:nn:ss.zzz) -

--- Code: ---16:22:34.652  Starting Log
16:22:42.740  TMyForm.FormCloseQuery Form 1
16:22:42.740  TMyForm.FormCloseQuery Visible=True
16:22:42.740  TMyForm.FormClose Form 1
16:22:49.759  Signal received #15
16:22:49.860  TMyForm.FormCloseQuery Form 0
16:22:49.860  TMyForm.FormCloseQuery Visible=True
16:22:49.860  TMyForm.FormClose Form 0
16:22:49.860  TMyForm.FormDestroy Form 0
16:22:49.964  TMyForm.FormCloseQuery Form 1
16:22:49.964  TMyForm.FormCloseQuery Visible=False
16:22:49.964  TMyForm.FormClose Form 1
16:22:49.964  TMyForm.FormDestroy Form 1
16:22:50.071  TMyForm.FormCloseQuery Form 2
....
16:22:50.410  The FormMain is closed
16:22:50.410  Signal received #1
16:22:50.410  Igoring second signal #1
--- End code ---

Note that the app is first affected by the shutdown at 42.740, one of the slave windows is hidden. Then 7 seconds later, the MainForm gets the message via my HandleSig() method ! And in this case, Form 1 is now hidden (and would be gone if CloseAction=caFree).

How and why does the slave window get this close signal before FormMain ?

If I send the app a SIGTERM with the kill command, no problems, it all works as it should. The issue is at shutdown where, I believe, System V or SystemD will send a SIGTERM in exactly the same way !

The attached project, should be compiled, then run (perhaps outside the IDE) and the computer told to restart. Find the log in $HOME and some demo text, written as each Window shuts down, in $HOME/junk/.

Any insight would be greatly appreciated !

Davo

dbannon:
OK,  I am so desperate  I respond to my own post !

Just to point out the problem seems to be in LCL, a "pure" FPC program works as expected. Thus -

--- 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";}};} ---program catchterm; uses SysUtils, BaseUnix; var   ExitNow : boolean;      MesgTime : integer;      RecSig : integer; procedure WriteLog(Stuff : string; Init : boolean = false);var T : TextFile;begin    AssignFile(T, 'catchterm.log');    if Init then begin        if FileExists('catchterm.log') then DeleteFile('catchterm.log');        rewrite(T);    end else        append(T);    writeln(T, FormatDateTime('hh:nn:ss.zzz ', now()) + '  ' + Stuff);    flush(T);    closeFile(T);end; // suggestion that absolutly miminal code allowed in a signal handler in C  ?procedure HandleSig(aSignal: LongInt); cdecl;begin    if aSignal <> SigTERM then exit;    // just ignore SigHUP, we act on SigTERM    if RecSig = 0 then begin        RecSig := aSignal;        writelog('SigTerm received');        ExitNow := True;            // we exit gracefully ??    end;                            // the shutdown does NOT commence until after handler exitsend; procedure DoExitStuff();   // do not write to screen from here !var i : integer = 0;begin    if RecSig > 0 then begin        while i < 50 do begin            sleep(100);            inc(i);            if i mod 10 = 0 then                WriteLog('I''m still here doing shutdown stuff ' + inttostr(i div 10));        end;    end;end; begin    ExitNow := False;    MesgTime := 0;    writelog('App started ', true);    FpSignal(SigTERM, @HandleSig);          // FpSignal lies, sets errorno but works as expected.    FpSignal(SigHUP,  @HandleSig);    while not ExitNow do begin              // just sit here and try to look busy        inc(MesgTime);        if MesgTime mod 500 = 0 then            WriteLog('I am still here');        sleep(10);    end;    DoExitStuff();  // here because we are exiting gracefully.    writelog('OK, we are done here.');end.

If you restart while this is running, you get this log -

--- Code: ---19:17:32.357   App started
19:17:37.616   I am still here
19:17:42.855   I am still here
19:17:48.600   I am still here
19:17:53.907   I am still here
19:17:59.469   I am still here
19:18:04.662   I am still here
19:18:09.872   I am still here
19:18:15.079   I am still here
19:18:20.292   I am still here
19:18:21.321   SigTerm received
19:18:22.333   I'm still here doing shutdown stuff 1
19:18:23.337   I'm still here doing shutdown stuff 2
19:18:24.340   I'm still here doing shutdown stuff 3
19:18:25.346   I'm still here doing shutdown stuff 4
19:18:26.352   I'm still here doing shutdown stuff 5
19:18:26.353   OK, we are done here.
--- End code ---
My experiments indicate an app can delay up to 90 seconds like this but apparently it depends on the OS. But not an LCL app.

So, why does LCL somehow decide to close down one or more child windows and then kill off the main one while its still trying to do its job ?

Davo

Davo

Thaddy:
Did you know about Application.OnQueryEndSession? Not form....That is where you should handle power down.
This is only interrupted/fails by hard powerdown or power outage and these cases can not be managed in code.

There are humungous amounts of examples, also on the forum.

dbannon:

--- Quote from: Thaddy on September 11, 2025, 01:35:02 pm ---Did you know about Application.OnQueryEndSession?

--- End quote ---

Nope, never heard of it !  I will have a good read !

Thanks

Davo

dbannon:

--- Quote from: Thaddy on September 11, 2025, 01:35:02 pm ---There are humungous amounts of examples, also on the forum.

--- End quote ---

There are five threads about it in the forum, general conclusion was not very useful, nothing in the last five years.

No mention of it in Lazarus Examples.

The on line help mentions it as one property of TApplication.

Not sure I'd call that humungous amounts of examples. But the wiki did mention it exists as an entry in the IDE toolbar under Additional. So, drop a TApplicationProperties on the mainform, seems to be able to make the project's Application properties available. And put a call to 'close' in the appropriate event, sure enough, it closes my forms before the app is KILL-ed. Wow !

Sadly, it then locks up in some endless loop until the usual 90 second timeout but that  is,  am sure, because I am using it incorrectly. I'll look for more of those humungous examples. Maybe I need to do the form by form closing in the OnQueryEndSession event rather that using my existing close recipe ? Calling close does sound a bit re-entrant.

Important to note, this event is NOT fired with the expected SigTERM or SigHUP, you do need to do a real powerdown to see it happen. Interesting.

Anyway, with this little hint I have made more progress than in the last three days ! Light at the end of the tunnel.....

Davo

Navigation

[0] Message Index

[#] Next page

Go to full version