comp.lang.ada
 help / color / mirror / Atom feed
* Problem with Delay Alternative in Finalization
@ 2012-05-19  2:30 Tim McGuire
  2012-05-19  6:12 ` Dmitry A. Kazakov
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Tim McGuire @ 2012-05-19  2:30 UTC (permalink / raw)



I am porting code from Solaris to Linux.

I am running in to a problem where a delay alternive used when in
finalization doesn't seem to be working properly.
The delay part never seems to happen.

The actual code is very complex, so I wrote a simple test to see if
the problem still existed.
I know there are better ways to do what this test program does, but I
am just trying to see if I can reproduce the problem from the actual
code.

I am using GCC 4.3.4 and to compile the program I issue the following
commands:
gnatname "*.[12].ada"
gnatmake token_test.2.ada -o token_test.exe



(spec)
===========
with Ada.Finalization;

package Test_Lock_Token is 

  Lock_Timeout_Exception : exception;
  Unknown_Exception : exception;
  type Lock_Token is
    Ada.Finalization.Limited_Controlled with null record;

private

  procedure Initialize (Object : in out Lock_Token);
  procedure Finalize (Object : in out Lock_Token);

end Test_Lock_Token;
===========

(body)
===========
package body Test_Lock_Token is 

  protected Lock_Type is
    entry Acquire;
    procedure Release;
  private
    Blocked : Boolean := False;
  end Lock_Type;

  protected body Lock_Type is
    entry Acquire when (not Blocked) is
    begin
      Blocked := True;
    end Acquire;
    procedure Release is
    begin
      if Blocked then
        Blocked := False;
      else
        raise Unknown_Exception;
    end Release;
  end Lock_Type;

  procedure Initialize (Object : in out Lock_Token) is
  begin
    select
      Lock_Type.Acquire
    or
      delay 2.0;
      raise Lock_Timeout_Exception;
    end select;
  end Initialize;

  procedure Finalize (Object : in out Lock_Token) is
  begin
    Lock_Type.Release;
  end Finalize;

end Test_Lock_Token;
===========

With a main of 
===========
with Ada.Text_Io;
with Test_Lock_Token;

Procedure Token_Test is
begin
  declare
    Token : Test_Lock_Token.Lock_Token;
  begin
    Ada.Text_Io.Put_Line ("Got Token");
    declare
      Token_2 : Test_Lock_Token.Lock_Token;
    begin
      Ada.Text_Io.Put_Line ("Got Token_2");
    exception
      When Errors : Test_Lock_Token.Lock_Timeout_Exception =>
        Ada.Text_Io.Put_Line ("Token_2 timed out!");
    end;
  exception
    When Errors : Test_Lock_Token.Lock_Timeout_Exception =>
      Ada.Text_Io.Put_Line("Token timed out!");
  end;
end Token_Test
===========

will lock up on the second attempt to get the token. 

Why doesn't the delay happen and raise the timeout exception?

It's not practical to rewrite the code unless absolutely neccessary.

Is there some compiler directive or pragma that I need to use in order
to get the delay alternative to work properly? 


Thanks,


Tim



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

* Re: Problem with Delay Alternative in Finalization
  2012-05-19  2:30 Problem with Delay Alternative in Finalization Tim McGuire
@ 2012-05-19  6:12 ` Dmitry A. Kazakov
  2012-05-19 12:51   ` Tim McGuire
  2012-05-19 19:46   ` Robert Matthews
  2012-05-19 17:33 ` Simon Wright
  2012-05-19 20:31 ` Robert A Duff
  2 siblings, 2 replies; 11+ messages in thread
From: Dmitry A. Kazakov @ 2012-05-19  6:12 UTC (permalink / raw)


On Fri, 18 May 2012 21:30:31 -0500, Tim McGuire wrote:

> I am running in to a problem where a delay alternive used when in
> finalization doesn't seem to be working properly.
> The delay part never seems to happen.

It is Program_Error to propagate an exception from Initialize, which is
what I think happens when you raise Lock_Timeout_Exception.

BTW, you can use task identification in order to allow reentrant locks.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: Problem with Delay Alternative in Finalization
  2012-05-19  6:12 ` Dmitry A. Kazakov
@ 2012-05-19 12:51   ` Tim McGuire
  2012-05-19 14:04     ` Dmitry A. Kazakov
  2012-05-19 19:46   ` Robert Matthews
  1 sibling, 1 reply; 11+ messages in thread
From: Tim McGuire @ 2012-05-19 12:51 UTC (permalink / raw)



I know about the task identification, the original code is a lot more
complex than the simple example I provided.

In the original code, Initialize actually calls another function which
has the select with the delay alternative, since sometimes the token
functionality is used directly rather than through finalization. I had
notice the direct use of the token did function properly, it was only
when used in finalization that it wasn't working.

The code works fine under Solaris with the Rational compiler, so is it
a GNAT issue? Or should it have not worked to start with?

And why doesn't the program crash on the Program_Error, rather than
just hang indefinitely?


On Sat, 19 May 2012 08:12:55 +0200, "Dmitry A. Kazakov"
<mailbox@dmitry-kazakov.de> wrote:

>On Fri, 18 May 2012 21:30:31 -0500, Tim McGuire wrote:
>
>> I am running in to a problem where a delay alternive used when in
>> finalization doesn't seem to be working properly.
>> The delay part never seems to happen.
>
>It is Program_Error to propagate an exception from Initialize, which is
>what I think happens when you raise Lock_Timeout_Exception.
>
>BTW, you can use task identification in order to allow reentrant locks.



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

* Re: Problem with Delay Alternative in Finalization
  2012-05-19 12:51   ` Tim McGuire
@ 2012-05-19 14:04     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 11+ messages in thread
From: Dmitry A. Kazakov @ 2012-05-19 14:04 UTC (permalink / raw)


On Sat, 19 May 2012 07:51:59 -0500, Tim McGuire wrote:

> The code works fine under Solaris with the Rational compiler, so is it
> a GNAT issue? Or should it have not worked to start with?

Raising exceptions from Initialize is a bad idea in any case.

> And why doesn't the program crash on the Program_Error, rather than
> just hang indefinitely?

4.3 is a relatively old compiler which might have problems with tasking. I
remember that adding a delay 0.01 at the beginning of the main program
helped to kick out tasks.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: Problem with Delay Alternative in Finalization
  2012-05-19  2:30 Problem with Delay Alternative in Finalization Tim McGuire
  2012-05-19  6:12 ` Dmitry A. Kazakov
@ 2012-05-19 17:33 ` Simon Wright
  2012-05-20  6:17   ` Simon Wright
  2012-05-19 20:31 ` Robert A Duff
  2 siblings, 1 reply; 11+ messages in thread
From: Simon Wright @ 2012-05-19 17:33 UTC (permalink / raw)


Tim McGuire <mcguire_tm2@yahoo.com> writes:

> I am running in to a problem where a delay alternive used when in
> finalization doesn't seem to be working properly.
> The delay part never seems to happen.

I ran this (after correcting a couple of minor compilation problems) on
a Mac. Using both GNAT GPL 2011 and GCC 4.7.0, the appearance on-screen
is as though the timeout didn't occur:

   $ ./token_test 
   Got Token
   Token timed out!

With both compilers, the debugger shows that the Lock_Timeout_Exception
did in fact happen. What happens next is confused .. Dmitry is probably
right.



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

* Re: Problem with Delay Alternative in Finalization
  2012-05-19  6:12 ` Dmitry A. Kazakov
  2012-05-19 12:51   ` Tim McGuire
@ 2012-05-19 19:46   ` Robert Matthews
  2012-05-20 16:46     ` Tim McGuire
  1 sibling, 1 reply; 11+ messages in thread
From: Robert Matthews @ 2012-05-19 19:46 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

> On Fri, 18 May 2012 21:30:31 -0500, Tim McGuire wrote:
> 
>> I am running in to a problem where a delay alternive used when in
>> finalization doesn't seem to be working properly.
>> The delay part never seems to happen.
> 
> It is Program_Error to propagate an exception from Initialize, which is
> what I think happens when you raise Lock_Timeout_Exception.
> 
> BTW, you can use task identification in order to allow reentrant locks.
> 

In the 2005 standard at 7.6.1 para 14.a: "It is not a bounded error for 
Initialize to propagate an exception. If Initialize propagates an exception, 
then no further calls on Initialize are performed, and those components that 
have already been initialized (either explicitly or by default) are 
finalized in the usual way."

So Program Error is not raised from Initialize - though
on general grounds it may well be best to avoid raising exceptions in
an Initialize.

Robert




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

* Re: Problem with Delay Alternative in Finalization
  2012-05-19  2:30 Problem with Delay Alternative in Finalization Tim McGuire
  2012-05-19  6:12 ` Dmitry A. Kazakov
  2012-05-19 17:33 ` Simon Wright
@ 2012-05-19 20:31 ` Robert A Duff
  2 siblings, 0 replies; 11+ messages in thread
From: Robert A Duff @ 2012-05-19 20:31 UTC (permalink / raw)


Tim McGuire <mcguire_tm2@yahoo.com> writes:

> Procedure Token_Test is
> begin
>   declare
>     Token : Test_Lock_Token.Lock_Token;
>   begin
>     Ada.Text_Io.Put_Line ("Got Token");
>     declare
>       Token_2 : Test_Lock_Token.Lock_Token;
>     begin
>       Ada.Text_Io.Put_Line ("Got Token_2");
>     exception
>       When Errors : Test_Lock_Token.Lock_Timeout_Exception =>
>         Ada.Text_Io.Put_Line ("Token_2 timed out!");
>     end;
>   exception
>     When Errors : Test_Lock_Token.Lock_Timeout_Exception =>
>       Ada.Text_Io.Put_Line("Token timed out!");
>   end;
> end Token_Test

Your code is full of syntax errors, so obviously this isn't
the code you ran.

But anyway, I think your exception handlers are confused.  An exception
handler in a block does not handle exceptions raise in the "declare"
part of the same block.  Ada's syntax is confusing in that regard -- it
LOOKS like they are handled.  This is something Java (for example)
gets right.  Exception handlers shouldn't be syntactically part
of blocks, procedure bodies, etc -- they should have a separate
statement.

- Bob



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

* Re: Problem with Delay Alternative in Finalization
  2012-05-19 17:33 ` Simon Wright
@ 2012-05-20  6:17   ` Simon Wright
  0 siblings, 0 replies; 11+ messages in thread
From: Simon Wright @ 2012-05-20  6:17 UTC (permalink / raw)


Simon Wright <simon@pushface.org> writes:

> Tim McGuire <mcguire_tm2@yahoo.com> writes:
>
>> I am running in to a problem where a delay alternive used when in
>> finalization doesn't seem to be working properly.
>> The delay part never seems to happen.
>
> I ran this (after correcting a couple of minor compilation problems) on
> a Mac. Using both GNAT GPL 2011 and GCC 4.7.0, the appearance on-screen
> is as though the timeout didn't occur:
>
>    $ ./token_test 
>    Got Token
>    Token timed out!
>
> With both compilers, the debugger shows that the Lock_Timeout_Exception
> did in fact happen. What happens next is confused .. Dmitry is probably
> right.

D'oh.

At 3 a.m. I realised what the problem is (at any rate, with the example
code; not sure whether this would affect the real thing).

As Bob Duff has already said, the exception when tryining to initialise
Token_2 means that the declare block is never entered. Try

   declare
      Token : Test_Lock_Token.Lock_Token;
   begin
      Ada.Text_IO.Put_Line ("Got Token");
      begin
         declare
            Token_2 : Test_Lock_Token.Lock_Token;
         begin
            null;
         end;
         Ada.Text_IO.Put_Line ("Got Token_2");
      exception
         when Errors : Test_Lock_Token.Lock_Timeout_Exception =>
            Ada.Text_IO.Put_Line ("Token_2 timed out!");
      end;
   exception
      when Errors : Test_Lock_Token.Lock_Timeout_Exception =>
         Ada.Text_IO.Put_Line("Token timed out!");
   end;



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

* Re: Problem with Delay Alternative in Finalization
  2012-05-19 19:46   ` Robert Matthews
@ 2012-05-20 16:46     ` Tim McGuire
  2012-05-20 17:01       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 11+ messages in thread
From: Tim McGuire @ 2012-05-20 16:46 UTC (permalink / raw)


On Sat, 19 May 2012 20:46:25 +0100, Robert Matthews
<ignore@ramatthews.free-online.co.uk> wrote:

>Dmitry A. Kazakov wrote:
>
>> On Fri, 18 May 2012 21:30:31 -0500, Tim McGuire wrote:
>> 
>>> I am running in to a problem where a delay alternive used when in
>>> finalization doesn't seem to be working properly.
>>> The delay part never seems to happen.
>> 
>> It is Program_Error to propagate an exception from Initialize, which is
>> what I think happens when you raise Lock_Timeout_Exception.
>> 
>> BTW, you can use task identification in order to allow reentrant locks.
>> 
>
>In the 2005 standard at 7.6.1 para 14.a: "It is not a bounded error for 
>Initialize to propagate an exception. If Initialize propagates an exception, 
>then no further calls on Initialize are performed, and those components that 
>have already been initialized (either explicitly or by default) are 
>finalized in the usual way."
>
>So Program Error is not raised from Initialize - though
>on general grounds it may well be best to avoid raising exceptions in
>an Initialize.
>
>Robert

I agree that raising exceptions in an Initialize isn't the best way to
do things.

However, this is the way the application was written for Solaris and I
am just porting it to Red Hat Linux.

The fact still remains that it appears that the Delay alternative is
not working properly in initialize, when compiled with GCC4.3.4.

Is there some way to fix this? Compiler switch, pragma, or maybe
upgrading compiler (i.e. newer version of GCC or GNATPRO)?





Tim



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

* Re: Problem with Delay Alternative in Finalization
  2012-05-20 16:46     ` Tim McGuire
@ 2012-05-20 17:01       ` Dmitry A. Kazakov
  2012-05-20 20:36         ` Simon Wright
  0 siblings, 1 reply; 11+ messages in thread
From: Dmitry A. Kazakov @ 2012-05-20 17:01 UTC (permalink / raw)


On Sun, 20 May 2012 11:46:55 -0500, Tim McGuire wrote:

> Is there some way to fix this? Compiler switch, pragma, or maybe
> upgrading compiler (i.e. newer version of GCC or GNATPRO)?

After fixing bugs, your code works with GNAT Pro 6.4.2.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: Problem with Delay Alternative in Finalization
  2012-05-20 17:01       ` Dmitry A. Kazakov
@ 2012-05-20 20:36         ` Simon Wright
  0 siblings, 0 replies; 11+ messages in thread
From: Simon Wright @ 2012-05-20 20:36 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On Sun, 20 May 2012 11:46:55 -0500, Tim McGuire wrote:
>
>> Is there some way to fix this? Compiler switch, pragma, or maybe
>> upgrading compiler (i.e. newer version of GCC or GNATPRO)?
>
> After fixing bugs, your code works with GNAT Pro 6.4.2.

And with GNAT GPL 2011, and with GCC 4.6.0, and with GCC 4.7.0.



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

end of thread, other threads:[~2012-05-20 20:37 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-19  2:30 Problem with Delay Alternative in Finalization Tim McGuire
2012-05-19  6:12 ` Dmitry A. Kazakov
2012-05-19 12:51   ` Tim McGuire
2012-05-19 14:04     ` Dmitry A. Kazakov
2012-05-19 19:46   ` Robert Matthews
2012-05-20 16:46     ` Tim McGuire
2012-05-20 17:01       ` Dmitry A. Kazakov
2012-05-20 20:36         ` Simon Wright
2012-05-19 17:33 ` Simon Wright
2012-05-20  6:17   ` Simon Wright
2012-05-19 20:31 ` Robert A Duff

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