comp.lang.ada
 help / color / mirror / Atom feed
* Finalization of static package variables
@ 2007-05-08 21:55 Manuel Collado
  2007-05-09  8:13 ` Alex R. Mosteo
  2007-05-09  8:20 ` Stephen Leake
  0 siblings, 2 replies; 25+ messages in thread
From: Manuel Collado @ 2007-05-08 21:55 UTC (permalink / raw)


Variables declared in the global scope of a package body seem not to be 
finalized automatically at the end of the whole program (using GNAT 
3.15p on WindowsXP).

If some of these variables contain certain GUI stuff, the program 
remains as a zombie process after the main procedure termination.

After several trial-and-error attemps, an Unchecked_Deallocation on 
these variables seems to do the trick (the whole program terminates 
smoothly). But this is probably not standard-conformant (ARM 13.11.2-16).

If there a standard way of forcing finalization of static package 
variables at program termination? I.e., without declaring them as 
dynamic, or inside a main procedure, or calling explicitly the 
finalization actions.

Thanks in advance.
-- 
Manuel Collado - http://lml.ls.fi.upm.es/~mcollado



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-08 21:55 Finalization of static package variables Manuel Collado
@ 2007-05-09  8:13 ` Alex R. Mosteo
  2007-05-09  8:20 ` Stephen Leake
  1 sibling, 0 replies; 25+ messages in thread
From: Alex R. Mosteo @ 2007-05-09  8:13 UTC (permalink / raw)


Manuel Collado wrote:

> Variables declared in the global scope of a package body seem not to be
> finalized automatically at the end of the whole program (using GNAT
> 3.15p on WindowsXP).
> 
> If some of these variables contain certain GUI stuff, the program
> remains as a zombie process after the main procedure termination.
> 
> After several trial-and-error attemps, an Unchecked_Deallocation on
> these variables seems to do the trick (the whole program terminates
> smoothly). But this is probably not standard-conformant (ARM 13.11.2-16).
> 
> If there a standard way of forcing finalization of static package
> variables at program termination? I.e., without declaring them as
> dynamic, or inside a main procedure, or calling explicitly the
> finalization actions.

You say using Unchecked_Deallocation does work, so that makes me think that
your global variables aren't Controlled objects but accesses to controlled
objects. Am I right? Deallocating a Controlled object indeed should trigger
a Finalize call on it.

Otherwise, I would expect that Finalize is called on any Controlled object
at program finalization, even if it's a variable at the library level in a
package body...



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-08 21:55 Finalization of static package variables Manuel Collado
  2007-05-09  8:13 ` Alex R. Mosteo
@ 2007-05-09  8:20 ` Stephen Leake
  2007-05-09 15:15   ` Adam Beneschan
  2007-05-09 22:19   ` Manuel Collado
  1 sibling, 2 replies; 25+ messages in thread
From: Stephen Leake @ 2007-05-09  8:20 UTC (permalink / raw)


Manuel Collado <m.collado@lml.ls.fi.upm.es> writes:

> Variables declared in the global scope of a package body seem not to
> be finalized automatically at the end of the whole program (using GNAT
> 3.15p on WindowsXP).

Is there some reason you are not using a more current version of GNAT?

> If some of these variables contain certain GUI stuff, the program
> remains as a zombie process after the main procedure termination.

Technically, that cannot be true; the "main procedure" is the
"environment task", and it does not "terminate" (in the Ada definition
of that word) until all of the tasks it has spawned have "terminated".

I think that what you are saying is that there are some tasks that
have not terminated when the main procedure is ready to terminate, and
that in fact those tasks never terminate.

> After several trial-and-error attemps, an Unchecked_Deallocation on
> these variables seems to do the trick (the whole program terminates
> smoothly). 

Unchecked_Deallocation is used on access variables (aka "pointers").
Such variables are _not_ automatically finalized by Ada; calling
Unchecked_Deallocation is the standard-compliant way to finalize them.

> But this is probably not standard-conformant (ARM 13.11.2-16).

This paragraph says:

    Evaluating a name that denotes a nonexistent object is erroneous.
    The execution of a call to an instance of Unchecked_Deallocation
    is erroneous if the object was created other than by an allocator
    for an access type whose pool is Name'Storage_Pool.

I don't see how that is relevant to your problem.

What version of the ARM are you quoting? When you say "ARM" without a
year, it implies "current" which means "Ada 2007" (or, informally,
"Ada 2005").

> If there a standard way of forcing finalization of static package
> variables at program termination? I.e., without declaring them as
> dynamic, or inside a main procedure, or calling explicitly the
> finalization actions.

If the type of the variable is derived from
Ada.Finalization.Controlled or Limited_Controlled, it will be
finalized when it goes out of scope. Otherwise, it won't be.

However, a static package variable never goes out of scope, so that is
no help.

Calling Unchecked_Deallocation does seem to be the correct approach to
what you need to do. Why is it a problem?

Posting code that outlines what you are doing would help a lot.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-09  8:20 ` Stephen Leake
@ 2007-05-09 15:15   ` Adam Beneschan
  2007-05-09 16:01     ` Markus E Leypold
  2007-05-09 22:00     ` Manuel Collado
  2007-05-09 22:19   ` Manuel Collado
  1 sibling, 2 replies; 25+ messages in thread
From: Adam Beneschan @ 2007-05-09 15:15 UTC (permalink / raw)


On May 9, 1:20 am, Stephen Leake <stephen_le...@stephe-leake.org>
wrote:
> Manuel Collado <m.coll...@lml.ls.fi.upm.es> writes:
> > Variables declared in the global scope of a package body seem not to
> > be finalized automatically at the end of the whole program (using GNAT
> > 3.15p on WindowsXP).
>
> Is there some reason you are not using a more current version of GNAT?
>
> > If some of these variables contain certain GUI stuff, the program
> > remains as a zombie process after the main procedure termination.
>
> Technically, that cannot be true; the "main procedure" is the
> "environment task", and it does not "terminate" (in the Ada definition
> of that word) until all of the tasks it has spawned have "terminated".
>
> I think that what you are saying is that there are some tasks that
> have not terminated when the main procedure is ready to terminate, and
> that in fact those tasks never terminate.

Except that Manuel never said he was using tasks.  I'm envisioning
that he probably has a controlled object whose initialization causes
some Windows process to be spawned (either directly or via some
function in some other GUI library), and finalization causes the
process to be terminated.


> If the type of the variable is derived from
> Ada.Finalization.Controlled or Limited_Controlled, it will be
> finalized when it goes out of scope. Otherwise, it won't be.
>
> However, a static package variable never goes out of scope, so that is
> no help.

No, I believe that all objects, including static package variables
*and* including allocated objects that have not yet been deallocated,
are supposed to be finalized when the environment task completes.
10.2(25), 7.6.1(10).

                                 -- Adam





^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-09 15:15   ` Adam Beneschan
@ 2007-05-09 16:01     ` Markus E Leypold
  2007-05-09 22:00     ` Manuel Collado
  1 sibling, 0 replies; 25+ messages in thread
From: Markus E Leypold @ 2007-05-09 16:01 UTC (permalink / raw)



Adam Beneschan <adam@irvine.com> writes:

> On May 9, 1:20 am, Stephen Leake <stephen_le...@stephe-leake.org>
> wrote:
>> Manuel Collado <m.coll...@lml.ls.fi.upm.es> writes:
>> > Variables declared in the global scope of a package body seem not to
>> > be finalized automatically at the end of the whole program (using GNAT
>> > 3.15p on WindowsXP).
>>
>> Is there some reason you are not using a more current version of GNAT?
>>
>> > If some of these variables contain certain GUI stuff, the program
>> > remains as a zombie process after the main procedure termination.
>>
>> Technically, that cannot be true; the "main procedure" is the
>> "environment task", and it does not "terminate" (in the Ada definition
>> of that word) until all of the tasks it has spawned have "terminated".
>>
>> I think that what you are saying is that there are some tasks that
>> have not terminated when the main procedure is ready to terminate, and
>> that in fact those tasks never terminate.
>
> Except that Manuel never said he was using tasks.  I'm envisioning
> that he probably has a controlled object whose initialization causes
> some Windows process to be spawned (either directly or via some
> function in some other GUI library), and finalization causes the
> process to be terminated.
>
>
>> If the type of the variable is derived from
>> Ada.Finalization.Controlled or Limited_Controlled, it will be
>> finalized when it goes out of scope. Otherwise, it won't be.
>>
>> However, a static package variable never goes out of scope, so that is
>> no help.
>
> No, I believe that all objects, including static package variables
> *and* including allocated objects that have not yet been deallocated,
> are supposed to be finalized when the environment task completes.
> 10.2(25), 7.6.1(10).

Absolutely right.

With Gnat, though, that isn't the case if the process is terminated by
an external signal, e.g. SIGINT from keyboard or the ^C handler in the
windows console.

I wonder wether it is that which is puzzling the OP.

Regards -- Markus



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-09 15:15   ` Adam Beneschan
  2007-05-09 16:01     ` Markus E Leypold
@ 2007-05-09 22:00     ` Manuel Collado
  2007-05-09 23:27       ` Adam Beneschan
  2007-05-10 10:57       ` Stephen Leake
  1 sibling, 2 replies; 25+ messages in thread
From: Manuel Collado @ 2007-05-09 22:00 UTC (permalink / raw)


Adam Beneschan escribi�:
> On May 9, 1:20 am, Stephen Leake <stephen_le...@stephe-leake.org>
> wrote:
>> Manuel Collado <m.coll...@lml.ls.fi.upm.es> writes:
>>> Variables declared in the global scope of a package body seem not to
>>> be finalized automatically at the end of the whole program (using GNAT
>>> 3.15p on WindowsXP).
>> Is there some reason you are not using a more current version of GNAT?

Using JEWL-1.6, last updated for GNAT-3.15p. Unable to use it with 
GPS200x (until now - probably some required libraries not properly 
installed).

>>
>>> If some of these variables contain certain GUI stuff, the program
>>> remains as a zombie process after the main procedure termination.
>> Technically, that cannot be true; the "main procedure" is the
>> "environment task", and it does not "terminate" (in the Ada definition
>> of that word) until all of the tasks it has spawned have "terminated".
>>
>> I think that what you are saying is that there are some tasks that
>> have not terminated when the main procedure is ready to terminate, and
>> that in fact those tasks never terminate.
> 
> Except that Manuel never said he was using tasks.  I'm envisioning
> that he probably has a controlled object whose initialization causes
> some Windows process to be spawned (either directly or via some
> function in some other GUI library), and finalization causes the
> process to be terminated.

Well, JEWL uses tasks internally. So, who knows...

> 
>> If the type of the variable is derived from
>> Ada.Finalization.Controlled or Limited_Controlled, it will be
>> finalized when it goes out of scope. Otherwise, it won't be.
>>
>> However, a static package variable never goes out of scope, so that is
>> no help.
> 
> No, I believe that all objects, including static package variables
> *and* including allocated objects that have not yet been deallocated,
> are supposed to be finalized when the environment task completes.
> 10.2(25), 7.6.1(10).

The fact is that there is a significant difference in behaviour between 
variables in the main procedure and static package variables. Example:


1. The following code always terminates smoothly.

--- main1.adb ---------------------------------------
with Jewl.Simple_Windows; use Jewl.Simple_Windows;

procedure Main1 is
    My_Frame: Frame_Type := Frame (200, 100, "Frame 1", 'Q');
    Ok: Button_Type := Button (My_Frame, (50, 20), 80, 25, "OK", 'Q');
    C: Character;
begin
    C := Next_Command;        -- just wait for any 'frame' event
end Main1;
----------------------------------------------------


2. The following alternate code may not terminate (remains as a zombie 
process). Requires explicit termination of the Frame, either by the [X] 
at the top-rigth corner or by 'Close(My_Frame)'.

--- main2.adb ---------------------------------------
procedure Main2 is
begin
    Do_Frame; -- just wait for any GUI event
end Main2;

--- pkg_frame.ads ---------------------------------------
package Pkg_Frame is
    procedure Do_Frame;
end Pkg_Frame;

--- main1.adb ---------------------------------------
with Jewl.Simple_Windows; use Jewl.Simple_Windows;

package body Pkg_Frame is
    My_Frame: Frame_Type := Frame (200, 100, "Frame 2", 'Q');
    Ok: Button_Type := Button (My_Frame, (50, 20), 80, 25, "OK", 'Q');
    C: Character;

    procedure Do_Frame is
    begin
       C := Next_Command; -- just wait for any GUI event
       -- POSSIBLE IMPROPER TERMINATION --
       -- may be fixed by enabling the following statement
       -- Close (My_Frame);
    end Do_Frame;

end Pkg_Frame;
----------------------------------------------------

Could the My_Frame declaration scope interfere with possible 
unterminated tasks inside JEWL?

Regards.
-- 
Manuel Collado - http://lml.ls.fi.upm.es/~mcollado



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-09  8:20 ` Stephen Leake
  2007-05-09 15:15   ` Adam Beneschan
@ 2007-05-09 22:19   ` Manuel Collado
  2007-05-10  5:38     ` AW: " Grein, Christoph (Fa. ESG)
  2007-05-10 10:55     ` Stephen Leake
  1 sibling, 2 replies; 25+ messages in thread
From: Manuel Collado @ 2007-05-09 22:19 UTC (permalink / raw)


Stephen Leake escribi�:
> Manuel Collado <m.collado@lml.ls.fi.upm.es> writes:
> 
>> Variables declared in the global scope of a package body seem not to
>> be finalized automatically at the end of the whole program (using GNAT
>> 3.15p on WindowsXP).
> [...]
>> After several trial-and-error attemps, an Unchecked_Deallocation on
>> these variables seems to do the trick (the whole program terminates
>> smoothly). 
> 
> Unchecked_Deallocation is used on access variables (aka "pointers").
> Such variables are _not_ automatically finalized by Ada; calling
> Unchecked_Deallocation is the standard-compliant way to finalize them.
> 
>> But this is probably not standard-conformant (ARM 13.11.2-16).
> 
> This paragraph says:
> 
>     Evaluating a name that denotes a nonexistent object is erroneous.
>     The execution of a call to an instance of Unchecked_Deallocation
>     is erroneous if the object was created other than by an allocator
>     for an access type whose pool is Name'Storage_Pool.
> 
> I don't see how that is relevant to your problem.

"... erroneous ... if the object was created other than by an allocator 
for an access type whose pool is Name'Storage_Pool."

Are static package variables allocated in this pool?

> 
> What version of the ARM are you quoting? When you say "ARM" without a
> year, it implies "current" which means "Ada 2007" (or, informally,
> "Ada 2005").

Doesn't "using GNAT 3.15p" give you any hint :-) ?

> [...]
> Posting code that outlines what you are doing would help a lot.

------------------------------------
package body Pkg_Dialog is
    My_Dialog: aliased Dialog_Type := Dialog (200, 100, "Dialog 3", 'Q');
    ...

    procedure Do_Dialog is
    begin
       ... exercise My_Dialog ...

       declare
          type Dialog_Access is access all Dialog_Type;
          procedure Dispose is
             new Ada.Unchecked_Deallocation (
             Object => Dialog_Type,
             Name   => Dialog_Access );
          Pointer: Dialog_Access := My_Dialog'access;
       begin
          Dispose (Pointer);  -- force My_Dialog finalization
       end;
    end Do_Dialog;

end Pkg_Dialog;
-----------------------------------

Regards.
-- 
Manuel Collado - http://lml.ls.fi.upm.es/~mcollado



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-09 22:00     ` Manuel Collado
@ 2007-05-09 23:27       ` Adam Beneschan
  2007-05-10  4:52         ` Jeffrey R. Carter
                           ` (2 more replies)
  2007-05-10 10:57       ` Stephen Leake
  1 sibling, 3 replies; 25+ messages in thread
From: Adam Beneschan @ 2007-05-09 23:27 UTC (permalink / raw)


On May 9, 3:00 pm, Manuel Collado <m.coll...@lml.ls.fi.upm.es> wrote:
> Adam Beneschan escribió:

> Well, JEWL uses tasks internally. So, who knows...

> > No, I believe that all objects, including static package variables
> > *and* including allocated objects that have not yet been deallocated,
> > are supposed to be finalized when the environment task completes.
> > 10.2(25), 7.6.1(10).
>
> The fact is that there is a significant difference in behaviour between
> variables in the main procedure and static package variables. Example:
>
> 1. The following code always terminates smoothly.
>
> --- main1.adb ---------------------------------------
> with Jewl.Simple_Windows; use Jewl.Simple_Windows;
>
> procedure Main1 is
>     My_Frame: Frame_Type := Frame (200, 100, "Frame 1", 'Q');
>     Ok: Button_Type := Button (My_Frame, (50, 20), 80, 25, "OK", 'Q');
>     C: Character;
> begin
>     C := Next_Command;        -- just wait for any 'frame' event
> end Main1;
> ----------------------------------------------------
>
> 2. The following alternate code may not terminate (remains as a zombie
> process). Requires explicit termination of the Frame, either by the [X]
> at the top-rigth corner or by 'Close(My_Frame)'.
>
> --- main2.adb ---------------------------------------
> procedure Main2 is
> begin
>     Do_Frame; -- just wait for any GUI event
> end Main2;
>
> --- pkg_frame.ads ---------------------------------------
> package Pkg_Frame is
>     procedure Do_Frame;
> end Pkg_Frame;
>
> --- main1.adb ---------------------------------------
> with Jewl.Simple_Windows; use Jewl.Simple_Windows;
>
> package body Pkg_Frame is
>     My_Frame: Frame_Type := Frame (200, 100, "Frame 2", 'Q');
>     Ok: Button_Type := Button (My_Frame, (50, 20), 80, 25, "OK", 'Q');
>     C: Character;
>
>     procedure Do_Frame is
>     begin
>        C := Next_Command; -- just wait for any GUI event
>        -- POSSIBLE IMPROPER TERMINATION --
>        -- may be fixed by enabling the following statement
>        -- Close (My_Frame);
>     end Do_Frame;
>
> end Pkg_Frame;
> ----------------------------------------------------
>
> Could the My_Frame declaration scope interfere with possible
> unterminated tasks inside JEWL?

Maybe.  I don't know anything about JEWL, so I don't know what the
declaration of "Frame_Type" is or what the "Frame" function does.  But
if the Frame function uses an allocator to create an access-to-task,
and if Frame_Type is a controlled type (or has controlled components)
whose Finalize routine does something that terminates that task, then
I can see how you would have a problem.  According to 9.3, if you (or
some routine in JEWL) have started a task with an allocator, then that
task depends on the master that elaborates the access-to-task *type*
(and any enclosing master).  Assuming the access type is declared at
the library level somewhere inside JEWL, then the only master it
depends on is the environment task.

When you declare My_Frame inside your main procedure, then as soon as
the procedure completes, My_Frame is finalized.  I'm assuming that its
Finalize routine (or the Finalize routine of a component) has code
that causes any task created by My_Frame's initialization to
terminate.  So this will cause things to terminate cleanly.

When you declare My_Frame at the library level, you've got a Catch-22
problem.  10.2(25) says, "When the environment task completes..., it
waits for the termination of all such tasks, and then finalizes any
remaining objects of the partition".  Again, assuming My_Frame's
finalize would terminate the task, the task termination would need to
be performed by the object finalization; but 10.2(25) says that task
termination must come *first*, before object finalization.  Yikes!

So it does look like you need to finalize My_Frame explicitly
(probably by calling Close).  It seems like there's a flaw somewhere.
Possibly, JEWL needs a "shutdown" routine to terminate any tasks that
are still running.  Offhand, though, I don't see any good way to
rearrange your program to make sure library-level objects are
finalized *before* the tasks are terminated, except by making sure all
your Frame_Type objects and such are declared inside some procedure,
which probably means making a lot of your packages subunits of some
big procedure, which is probably obnoxious.  I don't think Ada has a
way to tell the environment task that some objects, or objects of some
specified types, should be finalized *before* waiting for task
termination.  It would be helpful here, but there may not be a good
way to add a language feature to facilitate this.

                                         -- Adam





^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-09 23:27       ` Adam Beneschan
@ 2007-05-10  4:52         ` Jeffrey R. Carter
  2007-05-16  0:41           ` Randy Brukardt
  2007-05-10  8:16         ` Alex R. Mosteo
  2007-05-16  0:36         ` Randy Brukardt
  2 siblings, 1 reply; 25+ messages in thread
From: Jeffrey R. Carter @ 2007-05-10  4:52 UTC (permalink / raw)


Adam Beneschan wrote:
> 
> Maybe.  I don't know anything about JEWL, so I don't know what the
> declaration of "Frame_Type" is or what the "Frame" function does.  But
> if the Frame function uses an allocator to create an access-to-task,
> and if Frame_Type is a controlled type (or has controlled components)
> whose Finalize routine does something that terminates that task, then
> I can see how you would have a problem.  According to 9.3, if you (or
> some routine in JEWL) have started a task with an allocator, then that
> task depends on the master that elaborates the access-to-task *type*
> (and any enclosing master).  Assuming the access type is declared at
> the library level somewhere inside JEWL, then the only master it
> depends on is the environment task.

The task in JEWL is a singleton task declared in the specification of a 
library-level private package. This task keeps track of how many frames 
have been created and doesn't end until they've all been destroyed. The 
frame in the subprogram is destroyed when it is finalized when the 
subprogram returns; the frame in the package won't be finalized until 
the task ends. With the frame in a subprogram, the call to Close isn't 
strictly necessary (though it's a good idea). With the frame in the 
package, the call to Close is necessary. Otherwise, the task won't end 
until the frame is finalized, and the frame won't be finalized until the 
task ends.

-- 
Jeff Carter
"C++ is like giving an AK-47 to a monk, shooting him
full of crack and letting him loose in a mall and
expecting him to balance your checking account
'when he has the time.'"
Drew Olbrich
52



^ permalink raw reply	[flat|nested] 25+ messages in thread

* AW: Finalization of static package variables
  2007-05-09 22:19   ` Manuel Collado
@ 2007-05-10  5:38     ` Grein, Christoph (Fa. ESG)
  2007-05-10 10:55     ` Stephen Leake
  1 sibling, 0 replies; 25+ messages in thread
From: Grein, Christoph (Fa. ESG) @ 2007-05-10  5:38 UTC (permalink / raw)
  To: comp.lang.ada

When the main task terminates, all variables and constants go out of
scope, so also static variables and constants (those declared
immediately within library units, whether allocated by declaration or
via an allocator) are finalized.

If this is not the case with your compiler, it has a bug. The latest
Gnat 6.0.1 does finalize everything.


Eurocopter Deutschland GmbH
Sitz der Gesellschaft/Registered Office: Donauwoerth
Registergericht/Registration Court: Amtsgericht Augsburg HRB 16508
Vorsitzender des Aufsichtsrates/Chairman of the Supervisory Board: Dr. Lutz Bertling
Geschaeftsfuehrung/Board of Management:
Dr. Wolfgang Schoder, Vorsitzender/CEO; Friedrich-Wilhelm Hormel; Ralf Barnscheidt

CONFIDENTIALITY NOTICE 

This communication and the information it contains is intended for the addressee(s) named above and for no other persons or organizations. It is confidential and may be legally privileged and protected by law. The unauthorized use, copying or disclosure of this communication or any part of it is prohibited and may be unlawful. 
If you have received this communication in error, kindly notify us by return e-mail and discard and/or delete the communication. Thank you very much. 
It is possible for e-mails to be intercepted or affected by viruses. Whilst we maintain virus checks on our e-mails, we accept no liability for viruses or other material which might be introduced with this message. 



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-09 23:27       ` Adam Beneschan
  2007-05-10  4:52         ` Jeffrey R. Carter
@ 2007-05-10  8:16         ` Alex R. Mosteo
  2007-05-16  0:36         ` Randy Brukardt
  2 siblings, 0 replies; 25+ messages in thread
From: Alex R. Mosteo @ 2007-05-10  8:16 UTC (permalink / raw)


Adam Beneschan wrote:

> When you declare My_Frame at the library level, you've got a Catch-22
> problem.  10.2(25) says, "When the environment task completes..., it
> waits for the termination of all such tasks, and then finalizes any
> remaining objects of the partition".  Again, assuming My_Frame's
> finalize would terminate the task, the task termination would need to
> be performed by the object finalization; but 10.2(25) says that task
> termination must come *first*, before object finalization.  Yikes!

Ahhhh... good catch!



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-09 22:19   ` Manuel Collado
  2007-05-10  5:38     ` AW: " Grein, Christoph (Fa. ESG)
@ 2007-05-10 10:55     ` Stephen Leake
  2007-05-11 18:12       ` Manuel Collado
  1 sibling, 1 reply; 25+ messages in thread
From: Stephen Leake @ 2007-05-10 10:55 UTC (permalink / raw)


Manuel Collado <m.collado@lml.ls.fi.upm.es> writes:

> Stephen Leake escribi�:
>> Manuel Collado <m.collado@lml.ls.fi.upm.es> writes:
>>
>>> Variables declared in the global scope of a package body seem not to
>>> be finalized automatically at the end of the whole program (using GNAT
>>> 3.15p on WindowsXP).
>> [...]
>>> After several trial-and-error attemps, an Unchecked_Deallocation on
>>> these variables seems to do the trick (the whole program terminates
>>> smoothly).
>> Unchecked_Deallocation is used on access variables (aka "pointers").
>> Such variables are _not_ automatically finalized by Ada; calling
>> Unchecked_Deallocation is the standard-compliant way to finalize them.
>>
>>> But this is probably not standard-conformant (ARM 13.11.2-16).
>> This paragraph says:
>>     Evaluating a name that denotes a nonexistent object is erroneous.
>>     The execution of a call to an instance of Unchecked_Deallocation
>>     is erroneous if the object was created other than by an allocator
>>     for an access type whose pool is Name'Storage_Pool.
>> I don't see how that is relevant to your problem.
>
> "... erroneous ... if the object was created other than by an
> allocator for an access type whose pool is Name'Storage_Pool."
>
> Are static package variables allocated in this pool?

static package variables are created in the heap.

If they are _pointers_, the objects that they point to are allocated in
some pool.

There is a big difference between a pointer variable, and the object
it points to.

>> What version of the ARM are you quoting? When you say "ARM" without a
>> year, it implies "current" which means "Ada 2007" (or, informally,
>> "Ada 2005").
>
> Doesn't "using GNAT 3.15p" give you any hint :-) ?

Ah, sorry, forgot that part.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-09 22:00     ` Manuel Collado
  2007-05-09 23:27       ` Adam Beneschan
@ 2007-05-10 10:57       ` Stephen Leake
  1 sibling, 0 replies; 25+ messages in thread
From: Stephen Leake @ 2007-05-10 10:57 UTC (permalink / raw)


Manuel Collado <m.collado@lml.ls.fi.upm.es> writes:

> 2. The following alternate code may not terminate (remains as a zombie
> process). Requires explicit termination of the Frame, either by the
> [X] at the top-rigth corner or by 'Close(My_Frame)'.

That would seem to be normal, expected behavior for a GUI program; it
runs until the user ends it. 

Why is this a problem?

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-10 10:55     ` Stephen Leake
@ 2007-05-11 18:12       ` Manuel Collado
  2007-05-11 18:26         ` Robert A Duff
  0 siblings, 1 reply; 25+ messages in thread
From: Manuel Collado @ 2007-05-11 18:12 UTC (permalink / raw)


Stephen Leake escribi�:
> Manuel Collado <m.collado@lml.ls.fi.upm.es> writes:
>> Stephen Leake escribi�:
>>> Manuel Collado <m.collado@lml.ls.fi.upm.es> writes:
>>> ...
>>>> But this is probably not standard-conformant (ARM 13.11.2-16).
>>> This paragraph says:
>>>     Evaluating a name that denotes a nonexistent object is erroneous.
>>>     The execution of a call to an instance of Unchecked_Deallocation
>>>     is erroneous if the object was created other than by an allocator
>>>     for an access type whose pool is Name'Storage_Pool.
>>> I don't see how that is relevant to your problem.
>> "... erroneous ... if the object was created other than by an
>> allocator for an access type whose pool is Name'Storage_Pool."
>>
>> Are static package variables allocated in this pool?
> 
> static package variables are created in the heap.
> 
> If they are _pointers_, the objects that they point to are allocated in
> some pool.
> 
> There is a big difference between a pointer variable, and the object
> it points to.

That's what I've teached to my students for decades :-)

But an access variable can refer to a static variable. Is the following 
Ada95 code schema legal? What about Ada200x (or just Ada, if you want)? 
It seems to work in GNAT-3.15p (it lets finalize 'Edit'), but ...

-------------------------------------------------
package body View_Editor is

    Edit: aliased Dialog_Type :=
       Dialog (420, 350, "Conversion Rates", 'Q', Main_Font);

[...snipped...]

    procedure Editor_Destroy is
       type Dialog_Access is access all Dialog_Type;
       procedure Dispose is
          new Ada.Unchecked_Deallocation (
          Object => Dialog_Type,
          Name   => Dialog_Access );
       Pointer: Dialog_Access := Edit'access;
    begin
       Dispose (Pointer);
    end Editor_Destroy;

end View_Editor;
--------------------------------------------------

Thanks.
-- 
Manuel Collado - http://lml.ls.fi.upm.es/~mcollado



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-11 18:12       ` Manuel Collado
@ 2007-05-11 18:26         ` Robert A Duff
  2007-05-12 19:17           ` Finalization of static package variables - summary Manuel Collado
  0 siblings, 1 reply; 25+ messages in thread
From: Robert A Duff @ 2007-05-11 18:26 UTC (permalink / raw)


Manuel Collado <m.collado@lml.ls.fi.upm.es> writes:

> But an access variable can refer to a static variable. Is the following
> Ada95 code schema legal?

It is erroneous, which is the Ada term for "wrong, and will cause
totally unpredictable behavior at run time."  Most likely,
you will corrupt the heap data structures if you try to free
objects that are not heap allocated.

Note that if you erase the "Dispose", then Edit will be finalized when
program is done.

>...What about Ada200x (or just Ada, if you want)?

Same answer.

> It seems to work in GNAT-3.15p (it lets finalize 'Edit'), but ...
>
> -------------------------------------------------
> package body View_Editor is
>
>    Edit: aliased Dialog_Type :=
>       Dialog (420, 350, "Conversion Rates", 'Q', Main_Font);
>
> [...snipped...]
>
>    procedure Editor_Destroy is
>       type Dialog_Access is access all Dialog_Type;
>       procedure Dispose is
>          new Ada.Unchecked_Deallocation (
>          Object => Dialog_Type,
>          Name   => Dialog_Access );
>       Pointer: Dialog_Access := Edit'access;
>    begin
>       Dispose (Pointer);
>    end Editor_Destroy;
>
> end View_Editor;

- Bob



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables - summary
  2007-05-11 18:26         ` Robert A Duff
@ 2007-05-12 19:17           ` Manuel Collado
  2007-05-16  0:49             ` Randy Brukardt
  0 siblings, 1 reply; 25+ messages in thread
From: Manuel Collado @ 2007-05-12 19:17 UTC (permalink / raw)


Thanks to all who responded. Now it is clear that:

1.- Static packages variables are properly finalized at the end of the 
main task.

2.- There is a problem with JEWL, if modal dialogs are declared as 
static package variables.
2.1.- JEWL doesn't provide an explicit 'close' action for this kind of 
top level windows. It just provides one for 'frames'.
2.2.- After the main procedure ends, there is a deadlock between the 
main (environment) task and the internal JEWL message task (that is 
waiting for finalization of all top level windows).
2.3.- Being static variables, the mentioned modal dialogs cannot be 
'unchecked_deallocated' to force its finalization

To gain the possibility of declaring modal dialogs as static package 
variables, I've patched the JEWL sources to add a 'close()' procedure 
for modal dialogs.

Thanks again.
-- 
Manuel Collado - http://lml.ls.fi.upm.es/~mcollado



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-09 23:27       ` Adam Beneschan
  2007-05-10  4:52         ` Jeffrey R. Carter
  2007-05-10  8:16         ` Alex R. Mosteo
@ 2007-05-16  0:36         ` Randy Brukardt
  2007-05-16 14:06           ` Adam Beneschan
  2 siblings, 1 reply; 25+ messages in thread
From: Randy Brukardt @ 2007-05-16  0:36 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1488 bytes --]

"Adam Beneschan" <adam@irvine.com> wrote in message
news:1178753228.648765.89390@e65g2000hsc.googlegroups.com...
On May 9, 3:00 pm, Manuel Collado <m.coll...@lml.ls.fi.upm.es> wrote:
> Adam Beneschan escribi�:

> Well, JEWL uses tasks internally. So, who knows...

> > No, I believe that all objects, including static package variables
> > *and* including allocated objects that have not yet been deallocated,
> > are supposed to be finalized when the environment task completes.
> > 10.2(25), 7.6.1(10).
>
> The fact is that there is a significant difference in behaviour between
> variables in the main procedure and static package variables. Example:

This sounds awfully familiar to me; it's a problem that we had in Claw. The
problem you're having appears to be that the library you arer using (JEWL)
does not properly support library-level objects. We had a lot of trouble
with this in Claw, in the end we found a trick to determine when the
environment task is completing; then we have the main task forcibly
close/finalize all open windows. Otherwise, the program would go catatonic,
because the tasks would be waiting for the windows to close, but Ada says
that the tasks have to end first.

Moral: using an ancient library and an ancient compiler means that you'll
refind all of the bugs long ago worked out. Use a newer compiler, use a
library like Claw oe GWindows or even GtkAda, and you won't have these sorts
of issues...

                                     Randy.





^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-10  4:52         ` Jeffrey R. Carter
@ 2007-05-16  0:41           ` Randy Brukardt
  0 siblings, 0 replies; 25+ messages in thread
From: Randy Brukardt @ 2007-05-16  0:41 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.jrcarter.not@acm.nospam.org> wrote in message
news:cyx0i.45276$n_.17025@attbi_s21...
...
> The task in JEWL is a singleton task declared in the specification of a
> library-level private package. This task keeps track of how many frames
> have been created and doesn't end until they've all been destroyed. The
> frame in the subprogram is destroyed when it is finalized when the
> subprogram returns; the frame in the package won't be finalized until
> the task ends. With the frame in a subprogram, the call to Close isn't
> strictly necessary (though it's a good idea). With the frame in the
> package, the call to Close is necessary. Otherwise, the task won't end
> until the frame is finalized, and the frame won't be finalized until the
> task ends.

Unfortunately, that isn't possible if the owner of the window (frame) is
aborted or is terminated by an unexpected exception. (You can have a handler
in the latter case, but that's easy to forget.) We tried that approach first
with Claw, but the number of support calls about programs that wouldn't
terminate (and a lot of time wasted on our end before we realized that we
just had another instance of the same old user error) quickly proved the
silliness of that strategy.

Even if JEWL isn't technically broken in this case, it is unnecessarily
fragile.

BTW, the OP should know that Gnat 3.15p does this sort of finalization
correctly; some earlier versions didn't, but a lot of Claw bug reports
cleaned that up...

                            Randy.





^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables - summary
  2007-05-12 19:17           ` Finalization of static package variables - summary Manuel Collado
@ 2007-05-16  0:49             ` Randy Brukardt
  0 siblings, 0 replies; 25+ messages in thread
From: Randy Brukardt @ 2007-05-16  0:49 UTC (permalink / raw)


"Manuel Collado" <m.collado@lml.ls.fi.upm.es> wrote in message
news:46461336@news.upm.es...
...
> To gain the possibility of declaring modal dialogs as static package
> variables, I've patched the JEWL sources to add a 'close()' procedure
> for modal dialogs.

As I mentioned previously, this really doesn't work: if your program has a
bug and raises an unhandled exception, it will deadlock again (and probably
not even tell you what happened!). You could try to put handlers all over
the place, but that is an amazing pain and quite fragile.

I think you either have to use JEWL as it was intended (with modal dialogs
declared in subprograms; I can't think of any good reason to declare a modal
dialog in a package anyway: it can't live very long, since it prevents
everything else from working) or switch to a different GUI library. (I'm
partial to Claw, but any of them would work.)

                                  Randy.





^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-16  0:36         ` Randy Brukardt
@ 2007-05-16 14:06           ` Adam Beneschan
  2007-05-16 16:47             ` Jeffrey R. Carter
  2007-05-16 19:10             ` Randy Brukardt
  0 siblings, 2 replies; 25+ messages in thread
From: Adam Beneschan @ 2007-05-16 14:06 UTC (permalink / raw)


On May 15, 5:36 pm, "Randy Brukardt" <r...@rrsoftware.com> wrote:
> "Adam Beneschan" <a...@irvine.com> wrote in message
>
> news:1178753228.648765.89390@e65g2000hsc.googlegroups.com...
> On May 9, 3:00 pm, Manuel Collado <m.coll...@lml.ls.fi.upm.es> wrote:
>
> > Adam Beneschan escribió:
> > Well, JEWL uses tasks internally. So, who knows...
> > > No, I believe that all objects, including static package variables
> > > *and* including allocated objects that have not yet been deallocated,
> > > are supposed to be finalized when the environment task completes.
> > > 10.2(25), 7.6.1(10).
>
> > The fact is that there is a significant difference in behaviour between
> > variables in the main procedure and static package variables. Example:
>
> This sounds awfully familiar to me; it's a problem that we had in Claw. The
> problem you're having appears to be that the library you arer using (JEWL)
> does not properly support library-level objects. We had a lot of trouble
> with this in Claw, in the end we found a trick to determine when the
> environment task is completing; then we have the main task forcibly
> close/finalize all open windows.

So, to go back to a point I briefly mentioned in my previous post:
does Ada need a feature that would allow you to call your own
finalization procedure or something when the environment task is
completing, so that you don't have to do this using trickery?  Maybe
something like:

    package Ada.Finalization.Environment is
         type Finalization_Proc is access procedure;
         procedure At_Environment_Task_Completion (Proc : in
Finalization_Proc);
    end Ada.Finalization.Environment;

Then, the body of the "Environment_Task" implicit task would call the
main subprogram and then call any procedures registered with
At_Environment_Task_Completion, in arbitrary order; you could possibly
add an exception handler to the Environment_Task body to call the
finalization procedures too.

That would be a simple way to solve this sort of problem without
adding any language syntax.

                                      -- Adam




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-16 14:06           ` Adam Beneschan
@ 2007-05-16 16:47             ` Jeffrey R. Carter
  2007-05-16 19:10             ` Randy Brukardt
  1 sibling, 0 replies; 25+ messages in thread
From: Jeffrey R. Carter @ 2007-05-16 16:47 UTC (permalink / raw)


Adam Beneschan wrote:
> 
> So, to go back to a point I briefly mentioned in my previous post:
> does Ada need a feature that would allow you to call your own
> finalization procedure or something when the environment task is
> completing, so that you don't have to do this using trickery?  Maybe
> something like:
> 
>     package Ada.Finalization.Environment is
>          type Finalization_Proc is access procedure;
>          procedure At_Environment_Task_Completion (Proc : in
> Finalization_Proc);
>     end Ada.Finalization.Environment;
> 
> Then, the body of the "Environment_Task" implicit task would call the
> main subprogram and then call any procedures registered with
> At_Environment_Task_Completion, in arbitrary order; you could possibly
> add an exception handler to the Environment_Task body to call the
> finalization procedures too.
> 
> That would be a simple way to solve this sort of problem without
> adding any language syntax.

Not for this problem. This was simply a misunderstanding of how to use 
JEWL; JEWL windows should always be explicitly closed.

In the general case, I'd think this indicates a design problem, not a 
failure of the language.

-- 
Jeff Carter
"I like it when the support group complains that they have
insufficient data on mean time to repair bugs in Ada software."
Robert I. Eachus
91



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-16 14:06           ` Adam Beneschan
  2007-05-16 16:47             ` Jeffrey R. Carter
@ 2007-05-16 19:10             ` Randy Brukardt
  2007-05-22  4:41               ` christoph.grein
  1 sibling, 1 reply; 25+ messages in thread
From: Randy Brukardt @ 2007-05-16 19:10 UTC (permalink / raw)


"Adam Beneschan" <adam@irvine.com> wrote in message
news:1179324410.556097.234870@u30g2000hsc.googlegroups.com...
...
> So, to go back to a point I briefly mentioned in my previous post:
> does Ada need a feature that would allow you to call your own
> finalization procedure or something when the environment task is
> completing, so that you don't have to do this using trickery?

No, because your proposed "fix" is more complex than the trick, which is
simply to use Ada.Task_Identification:

-- In a library package:
with Ada.Task_Identification; use Ada.Task_Identification;

Env_Task_Id : constant Task_Id := Current_Task;

Now, in any task that you want to take special action if the main subprogram
has exited:

     if Is_Completed (Env_Task_Id) then

Originally, when I dreamt this up for Claw, no compilers actually
implemented it. Indeed, I asked the question to the ARG, which became
AI-206. When that was resolved, ACATS test CXC7004 was added to test it, so
it is likely that all current compilers support doing this. (Surely all of
the Windows ones do, we sent bug reports to all of them...)

So there is no need for something fancier, the capability already exists.

                            Randy.











^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-16 19:10             ` Randy Brukardt
@ 2007-05-22  4:41               ` christoph.grein
  2007-05-22  6:25                 ` tmoran
  0 siblings, 1 reply; 25+ messages in thread
From: christoph.grein @ 2007-05-22  4:41 UTC (permalink / raw)


On 16 Mai, 21:10, "Randy Brukardt" <r...@rrsoftware.com> wrote:
> No, because your proposed "fix" is more complex than the trick, which is
> simply to use Ada.Task_Identification:
>
> -- In a librarypackage:
> with Ada.Task_Identification; use Ada.Task_Identification;
>
> Env_Task_Id : constant Task_Id := Current_Task;
>
> Now, in any task that you want to take special action if the main subprogram
> has exited:
>
>      if Is_Completed (Env_Task_Id) then

There is no such function as is_Completed. Which do you mean:
   is_Terminated
or
   not is_Callable?




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-22  4:41               ` christoph.grein
@ 2007-05-22  6:25                 ` tmoran
  2007-05-22 22:19                   ` Randy Brukardt
  0 siblings, 1 reply; 25+ messages in thread
From: tmoran @ 2007-05-22  6:25 UTC (permalink / raw)


> >      if Is_Completed (Env_Task_Id) then
>
> There is no such function as is_Completed. Which do you mean:
>    is_Terminated
> or
>    not is_Callable?
  Is_Callable.  Download the free Claw from www.rrsoftware.com and
look in claw.adb to see.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Finalization of static package variables
  2007-05-22  6:25                 ` tmoran
@ 2007-05-22 22:19                   ` Randy Brukardt
  0 siblings, 0 replies; 25+ messages in thread
From: Randy Brukardt @ 2007-05-22 22:19 UTC (permalink / raw)


<tmoran@acm.org> wrote in message
news:7u6dnXGpNfteEc_bnZ2dnUVZ_uejnZ2d@comcast.com...
> > >      if Is_Completed (Env_Task_Id) then
> >
> > There is no such function as is_Completed. Which do you mean:
> >    is_Terminated
> > or
> >    not is_Callable?
>   Is_Callable.  Download the free Claw from www.rrsoftware.com and
> look in claw.adb to see.

Right. Shoulda checked more carefully...

            Randy.





^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2007-05-22 22:19 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-05-08 21:55 Finalization of static package variables Manuel Collado
2007-05-09  8:13 ` Alex R. Mosteo
2007-05-09  8:20 ` Stephen Leake
2007-05-09 15:15   ` Adam Beneschan
2007-05-09 16:01     ` Markus E Leypold
2007-05-09 22:00     ` Manuel Collado
2007-05-09 23:27       ` Adam Beneschan
2007-05-10  4:52         ` Jeffrey R. Carter
2007-05-16  0:41           ` Randy Brukardt
2007-05-10  8:16         ` Alex R. Mosteo
2007-05-16  0:36         ` Randy Brukardt
2007-05-16 14:06           ` Adam Beneschan
2007-05-16 16:47             ` Jeffrey R. Carter
2007-05-16 19:10             ` Randy Brukardt
2007-05-22  4:41               ` christoph.grein
2007-05-22  6:25                 ` tmoran
2007-05-22 22:19                   ` Randy Brukardt
2007-05-10 10:57       ` Stephen Leake
2007-05-09 22:19   ` Manuel Collado
2007-05-10  5:38     ` AW: " Grein, Christoph (Fa. ESG)
2007-05-10 10:55     ` Stephen Leake
2007-05-11 18:12       ` Manuel Collado
2007-05-11 18:26         ` Robert A Duff
2007-05-12 19:17           ` Finalization of static package variables - summary Manuel Collado
2007-05-16  0:49             ` Randy Brukardt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox