Recent

Author Topic: [Solved = False Alarm] Exit from within criticalsection? (application.inc)  (Read 3200 times)

PizzaProgram

  • Jr. Member
  • **
  • Posts: 62
  • ...developing Delphi apps since 25 years.
Dear Developers,
 Currently I'm debugging why I can not clean-exit from my app,
   (and eats up +50MB memory / day.)
My program calls 30 parallel processes, (10000/day,) and found this strange code where it stops during app-exit:

Code: Pascal  [Select][+][-]
  1. procedure TApplication.ProcessAsyncCallQueue;    
  2. ...
  3.     repeat
  4.       // remove top item from queue
  5.       System.EnterCriticalSection(CritSec);
  6.       try
  7.         if Cur.Top=nil then exit;  
  8. ...

IMHO this is fatal, because It will not leave the Critical section ever.
Am I wrong?

Laz v4.4 , FPC 3.2.2
« Last Edit: March 25, 2026, 07:29:35 pm by PizzaProgram »
x86_64-win64 --Win7 PRO 64bit HUN

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12896
  • FPC developer.
Re: Exif from within criticalsection? (application.inc)
« Reply #1 on: March 25, 2026, 12:20:37 pm »
It's wrapped in a try... statement , and you don't show what happens there, but one would expect a finally clause with the donecriticalsection. That runs always, also on EXIT.

wp

  • Hero Member
  • *****
  • Posts: 13555
Re: Exif from within criticalsection? (application.inc)
« Reply #2 on: March 25, 2026, 12:51:51 pm »
@PizzaProgram: Please edit the title of this thread: being the author of the fpExif library I am triggered by the "Exif" in the title - please replace it by "Exit"

Thaddy

  • Hero Member
  • *****
  • Posts: 19262
  • Glad to be alive.
Re: Exif from within criticalsection? (application.inc)
« Reply #3 on: March 25, 2026, 12:56:37 pm »
The finally should take care of LeaveCriticalSection.
If it doesn't ...............................
objects are fine constructs. You can even initialize them with constructors.

PizzaProgram

  • Jr. Member
  • **
  • Posts: 62
  • ...developing Delphi apps since 25 years.
Re: Exit from within criticalsection? (application.inc)
« Reply #4 on: March 25, 2026, 07:17:45 pm »
1. Sorry for bad title, but it is already fixed by someone.
2. Yes, there is a finally ... part of the try, but actually I'm shocked, because I'm using Pascal since 35 years, and I've always thought Exit will exit from the whole procedure or function.
Only the break command does quit from any: for / while / repeat / etc loops.

Is this a FreePascal thing?
 - or is it the same for Delphi 7 too ?

(I'll run a test today for D7)
x86_64-win64 --Win7 PRO 64bit HUN

Warfley

  • Hero Member
  • *****
  • Posts: 2066
Unless you do something very special, the finally section will always be called. If you exit a try block via exit, break, continue or an exception, it will still execute the finally block:
Code: Pascal  [Select][+][-]
  1. for i:=0 to 100 do
  2.   try
  3.     WriteLn('Skipping');
  4.     Continue;
  5.     WriteLn('This should not be printed');
  6.   finally
  7.     WriteLn('I is: ', i);
  8.   end;
  9.  
  10. // Or
  11. for i:=0 to 100 do
  12.   try
  13.     WriteLn('Breaking');
  14.     Break;
  15.     WriteLn('This should not be printed');
  16.   finally
  17.     WriteLn('I is: ', i);
  18.   end;
  19.  
  20. // Or
  21.   try
  22.     WriteLn('Exiting');
  23.     Exit;
  24.     WriteLn('This should not be printed');
  25.   finally
  26.     WriteLn('Finally is still executed');
  27.   end;

440bx

  • Hero Member
  • *****
  • Posts: 6528
Unless you do something very special, the finally section will always be called.
Off hand, the only "very special" thing that comes to mind that would prevent the "finally" part to be executed would be to call an O/S API that causes the program to terminate.

Is there another "very special" thing I'm missing that would cause the "finally" not to execute ?  Maybe calling "Setjump" to resume execution in a different frame ?
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Warfley

  • Hero Member
  • *****
  • Posts: 2066
Setjmp or other functions that directly mess with the instruction pointer come to mind. I'm not quire sure about inline assembly but raw jumps should also be able to mess this up. Basically anything that is outside the language.
But more importantly, because the try-finally blocks generate additional context info, if you jump out of them, the Cleanup of that context (it's an internal stack of finally frames) is not performed correctly, which will lead to all sorts of issues

440bx

  • Hero Member
  • *****
  • Posts: 6528
Basically anything that is outside the language.
That's what I thought.

As long as "stack frame disrupting" code is not used, the "finally(s)" should execute.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 19262
  • Glad to be alive.
Re: Exit from within criticalsection? (application.inc)
« Reply #9 on: March 26, 2026, 10:22:31 am »
Only the break command does quit from any: for / while / repeat / etc loops.

Is this a FreePascal thing?
Wrong. See warfeley's answer + example.
And no, this is not a freepascal thing: delphi behaves the exact same.
objects are fine constructs. You can even initialize them with constructors.

Xenno

  • Full Member
  • ***
  • Posts: 109
    • BS Programs
Statements like exit, break, continue, and goto are often considered harmful and should generally be avoided.

Although my teacher once challenged me, saying, “Why not? Assembler jumps around all the time.”
Lazarus 4.0, Windows 10, https://www.youtube.com/@bsprograms

440bx

  • Hero Member
  • *****
  • Posts: 6528
Statements like exit, break, continue, and goto are often considered harmful and should generally be avoided.
It is highly inappropriate to consider "exit", "break" and "continue" to be in the same league as the genuinely harmful "goto".  Those flow control statements, unlike the "goto" are _not_ harmful.  The reason why should be _obvious_.
\
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

MarkMLl

  • Hero Member
  • *****
  • Posts: 8572
Statements like exit, break, continue, and goto are often considered harmful and should generally be avoided.
It is highly inappropriate to consider "exit", "break" and "continue" to be in the same league as the genuinely harmful "goto".  Those flow control statements, unlike the "goto" are _not_ harmful.  The reason why should be _obvious_.
\

This is OT from the original question but there is a substantial body of opinion which /does/ equate  exit  etc. with  goto.

This is particularly the case when array processing is concerned, since there's a risk that flow control attempts to apply to one part of the array but not the remainder. That's why at a mathematical level one sometimes sees what would appear (to a programmer's eyes) to be quite weird application of transcendentals etc.

The doctrinal deviation exists, whether or not one agrees with it. I certainly have reservations, and feel that there would be a good argument for explicitly marking code bodies that contained anything like that as frangible, i.e. incautious use might break something /if/ used for array processing etc.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

440bx

  • Hero Member
  • *****
  • Posts: 6528
This is OT from the original question but there is a substantial body of opinion which /does/ equate  exit  etc. with  goto.
You're right, it is OT.  The problem is, there is at least one CRUCIAL difference between "break", "continue", "exit" and "goto".  Those who put them in the same class simply lack the understanding of some very basic programming concepts. 

The only thing those statements have in common with the "goto" is that they are all flow control statements and, if that's a "problem" for someone then, they should include "for", "while", "repeat", etc, which I hope the absurdity of their inclusion is obvious (if not painfully obvious.)

FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Xenno

  • Full Member
  • ***
  • Posts: 109
    • BS Programs
Not really OT. For short code it might easy to follow but the habbit might cause issues on longer code.

It could be written like this:

Code: Pascal  [Select][+][-]
  1. ...
  2.     CanContinue := True;
  3.     repeat
  4.       // remove top item from queue
  5.       System.EnterCriticalSection(CritSec);
  6.       try
  7.         if Cur.Top <> nil then begin
  8.           ...
  9.         end else
  10.           CanContinue := False;
  11.       finally
  12.         System.LeaveCriticalSection(CritSec);
  13.       end;
  14.     until not(CanContinue) or (OtherConds);      
  15. ...

The flow will be clearer.

exit, break, continue, goto are for machine. They are not for humans. The common reason for using them are to do shortcuts (or shorter code).

Luckily Pascal does not need break in a case statement.
Lazarus 4.0, Windows 10, https://www.youtube.com/@bsprograms

 

TinyPortal © 2005-2018