"ensure" hiding actual error

In my main program I have a "begin ensure end".
The "ensure" releases some resources.

If there is a syntax error somewhere deep, the program comes to 'ensure'
and shows me an error in the 'ensure', not the original error. Only if I
block out the 'ensure', does the actual error show.

I tried "rescue" with Exception, StandardError and ScriptError to print
the exception, but flow never reaches the 'rescue' block, it jumps ahead
to "ensure".

···

--
Posted via http://www.ruby-forum.com/.

This sounds strange because syntax errors should be caught earlier -
unless they stem from an "require" or "load". Can you post a short
example that reproduces the error?

Kind regards

robert

···

2008/10/1 Nit Khair <sentinel.2001@gmx.com>:

In my main program I have a "begin ensure end".
The "ensure" releases some resources.

If there is a syntax error somewhere deep, the program comes to 'ensure'
and shows me an error in the 'ensure', not the original error. Only if I
block out the 'ensure', does the actual error show.

I tried "rescue" with Exception, StandardError and ScriptError to print
the exception, but flow never reaches the 'rescue' block, it jumps ahead
to "ensure".

--
remember.guy do |as, often| as.you_can - without end

Robert Klemme wrote:

This sounds strange because syntax errors should be caught earlier -
unless they stem from an "require" or "load". Can you post a short
example that reproduces the error?

Kind regards

robert

Could you elaborate on that? At the moment, I am requiring a Module and
inheriting from a class. And the syntax error was in one of them.
However, as i said, when i remove the 'ensure' it correctly shows the
error in the relevant class.

I cannot recall if this error occurred when i had everything in one.
Will try to give a short sample. It's an ncurses-ruby program.

···

--
Posted via http://www.ruby-forum.com/\.

When Ruby interpreter loads a file it checks syntax (you can do
yourself with "ruby -c <script>"). If there is a syntax error that
will be shown before execution starts at all. If you require a file
and there is a syntax error in that there you will see an exception
stemming from the 'require':

1. error in main, 2. error in required:

15:20:13 OPSC_Gold_bas_dev_R1.2.3$ ruby -e 'puts 111+; require
ARGV.shift' <(echo /)
-e:1: syntax error, unexpected ';'
puts 111+; require ARGV.shift
          ^
15:20:22 OPSC_Gold_bas_dev_R1.2.3$ ruby -e 'puts 111; require
ARGV.shift' <(echo /)
111
-e:1:in `require': /dev/fd/63.rb:1: unterminated string meets end of
file (SyntaxError)
/dev/fd/63.rb:1: syntax error, unexpected tSTRING_END, expecting
tSTRING_CONTENT or tREGEXP_END or tSTRING_DBEG or tSTRING_DVAR
        from -e:1
15:20:26 OPSC_Gold_bas_dev_R1.2.3$

Cheers

robert

···

2008/10/1 Nit Khair <sentinel.2001@gmx.com>:

Robert Klemme wrote:

This sounds strange because syntax errors should be caught earlier -
unless they stem from an "require" or "load". Can you post a short
example that reproduces the error?

Could you elaborate on that?

--
remember.guy do |as, often| as.you_can - without end

Robert Klemme wrote:

Robert Klemme wrote:

This sounds strange because syntax errors should be caught earlier -
unless they stem from an "require" or "load". Can you post a short
example that reproduces the error?

I've tried to make a trivial case. Variable x is not initialized.

#!/usr/bin/env ruby -w

begin
  @test = x

ensure
  @test.strip
end

The error I get is:

  x.rb:8: warning: instance variable @test not initialized
  x.rb:8: undefined method `strip' for nil:NilClass (NoMethodError)

Now in real life, "@test = " calls a method elsewhere which may call
other methods. So i am clueless as to where the error actually is.

Now let's comment the ensure word. The new error message is:

  x.rb:4: undefined local variable or method `x' for main:Object
(NameError)

So this is currently my only solution.
In this particular case, I now add (before the ensure):

   rescue Exception => boom
     $stderr.print boom

and now I get the error. However, in my real curses program, it skips
the rescue clause and continues to go into the ensure.

···

2008/10/1 Nit Khair <sentinel.2001@gmx.com>:

--
Posted via http://www.ruby-forum.com/\.

Nit Khair wrote:

Now in real life, "@test = " calls a method elsewhere which may call
other methods. So i am clueless as to where the error actually is.

You caused another exception inside your ensure clause, so the previous
one got lost, so that's your mistake. If you want the original exception
to live to tell the tale, you cannot raise another in your ensure
clause. But if your ensure clause was correct, there wouldn't be any
problems with handling correctly the original exception.

TPR.

···

--
Posted via http://www.ruby-forum.com/\.

Adding to that: an uninitialized variable does not cause a syntax
error. IIRC initially this was about a syntax error.

Cheers

robert

···

2008/10/1 Thomas B. <tpreal@gmail.com>:

Nit Khair wrote:

Now in real life, "@test = " calls a method elsewhere which may call
other methods. So i am clueless as to where the error actually is.

You caused another exception inside your ensure clause, so the previous
one got lost, so that's your mistake. If you want the original exception
to live to tell the tale, you cannot raise another in your ensure
clause. But if your ensure clause was correct, there wouldn't be any
problems with handling correctly the original exception.

--
remember.guy do |as, often| as.you_can - without end

Robert Klemme wrote:

Nit Khair wrote:

Now in real life, "@test = " calls a method elsewhere which may call
other methods. So i am clueless as to where the error actually is.

You caused another exception inside your ensure clause, so the previous
one got lost, so that's your mistake. If you want the original exception
to live to tell the tale, you cannot raise another in your ensure
clause. But if your ensure clause was correct, there wouldn't be any
problems with handling correctly the original exception.

I am not following you. How have i caused another exception in the
ensure clause. I am not raising an exception in the ensure. The ensure
clause only has some statement to free resources. as in :

begin
my_form = create_....

ensure
my_form.free_form.
...
end

In the example i gave you, the stderr.print is printing the error from
above, but in my original ncurses program, it seems to directly go to
the ensure.

Let's say in my ensure I said:

  my_form.free_form if !my_form.nil?
then the program would just terminate silently.

Adding to that: an uninitialized variable does not cause a syntax
error. IIRC initially this was about a syntax error.

Okay, i was trying to give you a simple example. Sometimes it is a
variable - i may misspell it, or in some cases it is a syntax error.

Even currently as I am refactoring my code, I am sometimes getting the
correct error, sometimes I have to comment out "ensure" to get the
error.

Cheers

robert

Perhaps I should ask the question differently. Am i doing something
wrong, am i using the ensure clause incorrectly (the samples I started
with released these structures in the ensure). This is my first major
ruby app.
Thanks a lot for your time, Robert!

···

2008/10/1 Thomas B. <tpreal@gmail.com>:

--
Posted via http://www.ruby-forum.com/\.

Robert Klemme wrote:
>> Nit Khair wrote:
>>> Now in real life, "@test = " calls a method elsewhere which may call
>>> other methods. So i am clueless as to where the error actually is.
>>
>> You caused another exception inside your ensure clause, so the previous
>> one got lost, so that's your mistake. If you want the original exception
>> to live to tell the tale, you cannot raise another in your ensure
>> clause. But if your ensure clause was correct, there wouldn't be any
>> problems with handling correctly the original exception.
>

I am not following you. How have i caused another exception in the
ensure clause. I am not raising an exception in the ensure. The ensure
clause only has some statement to free resources. as in :

begin
my_form = create_....

ensure
my_form.free_form.
...
end

What happens here if my_form never got a value because there was an error
previous that made create_... invalid?

What Thomas is saying is that there is an exception being raised by the code
present in your ensure block.

···

On Wed, Oct 1, 2008 at 9:08 AM, Nit Khair <sentinel.2001@gmx.com> wrote:

> 2008/10/1 Thomas B. <tpreal@gmail.com>:

In the example i gave you, the stderr.print is printing the error from
above, but in my original ncurses program, it seems to directly go to
the ensure.

Let's say in my ensure I said:

my_form.free_form if !my_form.nil?
then the program would just terminate silently.

> Adding to that: an uninitialized variable does not cause a syntax
> error. IIRC initially this was about a syntax error.
>

Okay, i was trying to give you a simple example. Sometimes it is a
variable - i may misspell it, or in some cases it is a syntax error.

Even currently as I am refactoring my code, I am sometimes getting the
correct error, sometimes I have to comment out "ensure" to get the
error.

> Cheers
>
> robert

Perhaps I should ask the question differently. Am i doing something
wrong, am i using the ensure clause incorrectly (the samples I started
with released these structures in the ensure). This is my first major
ruby app.
Thanks a lot for your time, Robert!
--
Posted via http://www.ruby-forum.com/\.

--
"Hey brother Christian with your high and mighty errand, Your actions speak
so loud, I can't hear a word you're saying."

-Greg Graffin (Bad Religion)

Nit Khair wrote:

Robert Klemme wrote:
I am not following you. How have i caused another exception in the
ensure clause. I am not raising an exception in the ensure. The ensure
clause only has some statement to free resources. as in :

In the example you gave, where your ensure clause is @test.strip, you
did raise another exception, the "undefined method `strip' for
nil:NilClass (NoMethodError)" namely. Your ensure clause should do its
best not to raise any exception, or else the original exception is lost,
as you see.

Perhaps I should ask the question differently. Am i doing something
wrong, am i using the ensure clause incorrectly (the samples I started
with released these structures in the ensure). This is my first major
ruby app.

You are using the ensure correctly. The problem is that under some
circumstances the code in your ensure clause raises an exception. Maybe
you should use a separate begin rescue end inside your ensure clause.

TPR.

···

--
Posted via http://www.ruby-forum.com/\.

Glen Holcomb wrote:

>> problems with handling correctly the original exception.
ensure
my_form.free_form.
...
end

What happens here if my_form never got a value because there was an
error
previous that made create_... invalid?

What Thomas is saying is that there is an exception being raised by the
code
present in your ensure block.

Fine. I get that. So is there a better or correct way of doing this so
that I get the original error that was raised.

Aaaah. so you mean if i check for my_form before freeing, then ... since
no new exception is raised, the original exception will be displayed.
So I _should_ say:

ensure
if !my_form.nil?
   my_form.free ... etc
end

···

On Wed, Oct 1, 2008 at 9:08 AM, Nit Khair <sentinel.2001@gmx.com> wrote:

--
Posted via http://www.ruby-forum.com/\.

Yeah!

···

On Wed, Oct 1, 2008 at 9:32 AM, Nit Khair <sentinel.2001@gmx.com> wrote:

Glen Holcomb wrote:
> On Wed, Oct 1, 2008 at 9:08 AM, Nit Khair <sentinel.2001@gmx.com> wrote:
>
>> >> problems with handling correctly the original exception.
>> ensure
>> my_form.free_form.
>> ...
>> end
>>
>
> What happens here if my_form never got a value because there was an
> error
> previous that made create_... invalid?
>
> What Thomas is saying is that there is an exception being raised by the
> code
> present in your ensure block.
>
>
Fine. I get that. So is there a better or correct way of doing this so
that I get the original error that was raised.

Aaaah. so you mean if i check for my_form before freeing, then ... since
no new exception is raised, the original exception will be displayed.
So I _should_ say:

ensure
if !my_form.nil?
  my_form.free ... etc
end
--
Posted via http://www.ruby-forum.com/\.

--
"Hey brother Christian with your high and mighty errand, Your actions speak
so loud, I can't hear a word you're saying."

-Greg Graffin (Bad Religion)

Generally, the right way is to put the initialization _before_
the begin/ensure block:

    resource = init_resource
    begin
      # do something with resource
    ensure
      resource.close
    end

If all you do in the ensure block is to clean up the resource,
it is useless to put the resource initialization in the begin/ensure
block, because if the initialization fails, there's nothing to
cleanup anyway.

Stefan

···

2008/10/1 Nit Khair <sentinel.2001@gmx.com>:

Glen Holcomb wrote:

On Wed, Oct 1, 2008 at 9:08 AM, Nit Khair <sentinel.2001@gmx.com> wrote:

>> problems with handling correctly the original exception.
ensure
my_form.free_form.
...
end

What happens here if my_form never got a value because there was an
error
previous that made create_... invalid?

What Thomas is saying is that there is an exception being raised by the
code
present in your ensure block.

Fine. I get that. So is there a better or correct way of doing this so
that I get the original error that was raised.

Aaaah. so you mean if i check for my_form before freeing, then ... since
no new exception is raised, the original exception will be displayed.
So I _should_ say:

Stefan Lang wrote:

What happens here if my_form never got a value because there was an

Aaaah. so you mean if i check for my_form before freeing, then ... since
no new exception is raised, the original exception will be displayed.
So I _should_ say:

Generally, the right way is to put the initialization _before_
the begin/ensure block:

    resource = init_resource
    begin
      # do something with resource
    ensure
      resource.close
    end

If all you do in the ensure block is to clean up the resource,
it is useless to put the resource initialization in the begin/ensure
block, because if the initialization fails, there's nothing to
cleanup anyway.

Stefan

Very interesting answer. Let me be honest -- I've been lost as to where
to start the begin block. Is there any guideline in ruby?

I spent many years in Java where the style was:

try {
   resource = init_resource
} catch (exception) {}
finally {
   resource.close
}

I was following that pattern.

My apps basically:

a. create fields, forms and windows.
b. call key_handler loop
c. cleanup resources when key_handler quits

thanks a lot for valuable thoughts.

···

2008/10/1 Nit Khair <sentinel.2001@gmx.com>:

--
Posted via http://www.ruby-forum.com/\.

This is common in Java, but it is incorrect.

What happens if init_resource() throws an exception?

Dave

···

On Oct 2, 2008, at 7:39 AM, Nit Khair wrote:

I spent many years in Java where the style was:

try {
  resource = init_resource
} catch (exception) {}
finally {
  resource.close
}

Dave Thomas wrote:

···

On Oct 2, 2008, at 7:39 AM, Nit Khair wrote:

I spent many years in Java where the style was:

try {
  resource = init_resource
} catch (exception) {}
finally {
  if resource != null { resource.close }
}

This is common in Java, but it is incorrect.

What happens if init_resource() throws an exception?

Dave

Oops I forgot to mention that in finally {} one would check for resource
not being nil. Corrected above.
--
Posted via http://www.ruby-forum.com/\.

The pattern is still broken - or put it differently: overly complex. This is easier and as safe - and you can make the resource final and avoid accidental reassignment:

final Resource res = initResource();
try {
   res.use();
}
finally {
   res.cleanup();
}

Cheers

  robert

···

On 02.10.2008 14:48, Nit Khair wrote:

Dave Thomas wrote:

On Oct 2, 2008, at 7:39 AM, Nit Khair wrote:

I spent many years in Java where the style was:

try {
  resource = init_resource
} catch (exception) {}
finally {
  if resource != null { resource.close }
}

This is common in Java, but it is incorrect.

What happens if init_resource() throws an exception?

Oops I forgot to mention that in finally {} one would check for resource not being nil. Corrected above.

Robert Klemme wrote:

}

This is common in Java, but it is incorrect.

What happens if init_resource() throws an exception?

Oops I forgot to mention that in finally {} one would check for resource
not being nil. Corrected above.

The pattern is still broken - or put it differently: overly complex.
This is easier and as safe - and you can make the resource final and
avoid accidental reassignment:

final Resource res = initResource();
try {
   res.use();
   res.use();
   res.use();
   res.use();
}
finally {
   res.cleanup();
}

Cheers

  robert

Actually, I have left Java 4 years back. However, that being my last
programming language i still tend to thing in that way. IIRC, the above
pattern is used commonly because most, if not all, books gave it in
their samples. Take file opening or a database connection, for example.

Since it can throw a file not found exception, or a database connection
etc exception, the JDBC tutorials will recommend:

declare db variable
try {
   db = create_dbconnection(...)
   db.use

}
catch (ex){}
finally { cleanup code }

Anyway, I'd like to ask, if I use your suggested pattern of opening a
file or creating a resource before a begin/rescue/ensure block, would
that not mean i am not trapping failures from that. (I am just unused to
thinking this way! Could you point me to some code that illustrates
this.

Also, is there a quick way to know what exceptions a method can throw ?
Or is that not relevant ?

···

On 02.10.2008 14:48, Nit Khair wrote:

--
Posted via http://www.ruby-forum.com/\.

Robert Klemme wrote:

}

This is common in Java, but it is incorrect.

What happens if init_resource() throws an exception?

Oops I forgot to mention that in finally {} one would check for resource not being nil. Corrected above.

The pattern is still broken - or put it differently: overly complex.
This is easier and as safe - and you can make the resource final and
avoid accidental reassignment:

final Resource res = initResource();
try {
   res.use();
}
finally {
   res.cleanup();
}

Actually, I have left Java 4 years back. However, that being my last programming language i still tend to thing in that way. IIRC, the above pattern is used commonly because most, if not all, books gave it in their samples. Take file opening or a database connection, for example.

Well, books are dead wood. You always have to apply your own reasoning. It is not too uncommon for multiple books repeating the same error. In my experience it is best to take every advice with a grain of salt and apply own reasoning.

Since it can throw a file not found exception, or a database connection etc exception, the JDBC tutorials will recommend:

declare db variable
try {
   db = create_dbconnection(...)
   db.use

}
catch (ex){}
finally { cleanup code }

Anyway, I'd like to ask, if I use your suggested pattern of opening a file or creating a resource before a begin/rescue/ensure block, would that not mean i am not trapping failures from that. (I am just unused to thinking this way! Could you point me to some code that illustrates this.

Since we did not talk about rescue clauses so far (apart from your example above) there was never exception handling - regardless of placement of ensure / finally blocks.

When using my pattern you can catch errors more selectively:

try {
   Connection conn = getConnection();
   try {
     Statement st = conn.createStatement();
     ...
   }
   catch (SQLException e) {
     System.err.println("Conn use error: " + e.getMessage());
   }
   finally {
     close(conn);
   }
}
catch (SQLException e) {
   System.err.println("Conn init error: " + e.getMessage());
}

If you do not like the nesting you can refactor and extract the inner part into another method.

Also, is there a quick way to know what exceptions a method can throw ? Or is that not relevant ?

In Ruby: No, you would have to look at the code of a method and all methods which were called etc. Documentation is the fastest way I know of.

In Java: all methods can throw sub classes of all the checked exceptions listed in the signature plus all sub classes of RuntimeException and Error.

Kind regards

  robert

···

On 05.10.2008 18:31, Nit Khair wrote:

On 02.10.2008 14:48, Nit Khair wrote: