|
|||
|
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 |
|
|
||||
|
||||
|
|
|
|||
|
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 |
|
|||
|
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. |
|
|||
|
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 |
|
|||
|
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. |
|
|||
|
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 |
|
|||
|
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 |
|
|||
|
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; |
|
|||
|
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 |
|
|||
|
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 |
|
|||
|
"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. |
|
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|