[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

at_exit handler *except* for fatal runtime error

synergism

9/18/2008 12:45:00 PM

How do we execute a handler (I assume via at_exit) when a program
terminates *except* when there was a fatal runtime error (e.g. any
error such as "divide by zero" that terminates the program)?

We thought perhaps 'caller' would give us some clues but it turns out
to be useless.

Ben
15 Answers

Alex Fenton

9/18/2008 1:01:00 PM

0

synergism wrote:
> How do we execute a handler (I assume via at_exit) when a program
> terminates *except* when there was a fatal runtime error (e.g. any
> error such as "divide by zero" that terminates the program)?

Inspect the value of $! (or $ERROR_INFO) in your at_exit handler. This
will contain the last exception raised. eg

Kernel.at_exit {
if $!.kind_of? ZeroDivisionError
puts "don't run"
else
puts "run it"
end
}

5 / 0


hth
a

Brian Candler

9/18/2008 1:03:00 PM

0

synergism wrote:
> How do we execute a handler (I assume via at_exit) when a program
> terminates *except* when there was a fatal runtime error (e.g. any
> error such as "divide by zero" that terminates the program)?

"divide by zero" isn't a fatal error - you can catch it. But if you call
"exit!" then the program will abort without running at_exit handlers.

begin
0/0
rescue ZeroDivisionError
exit!
end

So,if by "fatal runtime error" you just mean "any uncaught exception",
then you can just wrap your entire program with

begin
... rest of program
rescue Exception
exit!
end
--
Posted via http://www.ruby-....

DMisener

9/18/2008 3:07:00 PM

0

Our situation is a little more complicated:

In our particular case we are creating run-time at_exit{} handlers

To give a concrete example:

We have a generic OpenOutputFile(...) routine which opens a "tentative
output" file
(output which is conditional on the module successfully completing).
We generate a temporary work file and at_exit we rename this file to
its "permanent name".
If the program aborts for any reason, this rename should not happen
( we do leave the failed working file around for later problem
investigation)



On Sep 18, 10:03 am, Brian Candler <b.cand...@pobox.com> wrote:
> synergism wrote:
> > How do we execute a handler (I assume via at_exit) when a program
> > terminates *except* when there was a fatal runtime error (e.g. any
> > error such as "divide by zero" that terminates the program)?
>
> "divide by zero" isn't a fatal error - you can catch it. But if you call
> "exit!" then the program will abort without running at_exit handlers.
>
> begin
>   0/0
> rescue ZeroDivisionError
>   exit!
> end
>
> So,if by "fatal runtime error" you just mean "any uncaught exception",
> then you can just wrap your entire program with
>
> begin
>   ... rest of program
> rescue Exception
>   exit!
> end
> --
> Posted viahttp://www.ruby-....

Robert Klemme

9/18/2008 4:03:00 PM

0

2008/9/18 synergism <synergism@gmail.com>:
> How do we execute a handler (I assume via at_exit) when a program
> terminates *except* when there was a fatal runtime error (e.g. any
> error such as "divide by zero" that terminates the program)?

You can use exit! for this:

18:09:02 ~$ ruby -e 'at_exit { puts "exiting" }'
exiting
18:09:08 ~$ ruby -e 'at_exit { puts "exiting" }; exit 1'
exiting
18:09:14 ~$ ruby -e 'at_exit { puts "exiting" }; raise "Foo"'
exiting
-e:1: Foo (RuntimeError)
18:09:21 ~$ ruby -e 'at_exit { puts "exiting" }; exit! 1'
18:09:27 ~$

Catch specific errors and use exit! to exit the program. Then your
handlers won't be invoked.

Cheers

robert

--
use.inject do |as, often| as.you_can - without end

DMisener

9/18/2008 4:32:00 PM

0

On Sep 18, 1:03 pm, Robert Klemme <shortcut...@googlemail.com> wrote:
> 2008/9/18 synergism <synerg...@gmail.com>:
>
> > How do we execute a handler (I assume via at_exit) when a program
> > terminates *except* when there was a fatal runtime error (e.g. any
> > error such as "divide by zero" that terminates the program)?
>
> You can use exit! for this:
>
....
> -e:1: Foo (RuntimeError)
> 18:09:21 ~$ ruby -e 'at_exit { puts "exiting" }; exit! 1'
> 18:09:27 ~$
>
> Catch specific errors and use exit! to exit the program.  Then your
> handlers won't be invoked.
>

But out above example we want to suppress the file rename for any
"unanticipated exception" -- which
is just the opposite of the solution you presented :=).


ara.t.howard

9/18/2008 4:58:00 PM

0


On Sep 18, 2008, at 9:02 AM, DMisener wrote:

> Our situation is a little more complicated:
>
> In our particular case we are creating run-time at_exit{} handlers
>
> To give a concrete example:
>
> We have a generic OpenOutputFile(...) routine which opens a "tentative
> output" file
> (output which is conditional on the module successfully completing).
> We generate a temporary work file and at_exit we rename this file to
> its "permanent name".
> If the program aborts for any reason, this rename should not happen
> ( we do leave the failed working file around for later problem
> investigation)


you can do this

at_exit {
rename_files unless $!
}

but you can also make it vastly simpler: do not use at exit handlers

setup a global list of renames to occur, for instance

module Rename
Map = {}

def file hash = {}
src, dst, *ignored = hash.to_a.first
Map[src.to_s] = dst.to_s
end

def files!
require 'fileutils'
Map.each{|src,dst| FileUtils.mv src, dst}
Map.clear
end

extend self
end

then, in the code, add files to be renamed

Rename.file 'foo' => 'bar'

this does not rename the file, it only notes that it needs to be done
later

now *as the last line of your program do*

Rename.files!

since this line is the last line of you program, it will never execute
under exceptional or error conditions. if you prefer you can then
wrap this up with an at_exit handler

at_exit {
Rename.files! unless $!
}

but be warned - calling exit or exit! itself will set $!


cfp:~ > ruby -e' begin; exit; ensure; p $!.class; end '
SystemExit


so, in fact, you have to be very, very, very careful about doing
things in at exit handlers based on 'error' conditions. this is a bug

at_exit{ cleanup! unless $! }
exit 0

that's why a solution that does not depend on at_exit or $! is much
better - simply defer the renaming until the very end. it's a sure
thing that you'll introduce bugs otherwise.


in any case it seems like you are working too hard - just 'normal'
ruby code performs *exactly* as per your requirements anyhow

do_the_work
rename_the_file # does *not* execute if previous line raises

cheers.


a @ http://codeforp...
--
we can deny everything, except that we have the possibility of being
better. simply reflect on that.
h.h. the 14th dalai lama




Robert Klemme

9/18/2008 8:11:00 PM

0

On 18.09.2008 18:31, DMisener wrote:
> On Sep 18, 1:03 pm, Robert Klemme <shortcut...@googlemail.com> wrote:
>> 2008/9/18 synergism <synerg...@gmail.com>:
>>
>>> How do we execute a handler (I assume via at_exit) when a program
>>> terminates *except* when there was a fatal runtime error (e.g. any
>>> error such as "divide by zero" that terminates the program)?
>> You can use exit! for this:
>>
> ...
>> -e:1: Foo (RuntimeError)
>> 18:09:21 ~$ ruby -e 'at_exit { puts "exiting" }; exit! 1'
>> 18:09:27 ~$
>>
>> Catch specific errors and use exit! to exit the program. Then your
>> handlers won't be invoked.
>>
>
> But out above example we want to suppress the file rename for any
> "unanticipated exception" -- which
> is just the opposite of the solution you presented :=).

Oh, come on. You can easily use that information to build what you want.

robert

Robert Dober

9/19/2008 9:57:00 AM

0

On Thu, Sep 18, 2008 at 10:07 PM, Robert Klemme
> Oh, come on. You can easily use that information to build what you want.
>
> robert
>
>
Hmm maybe not Robert, my feeling is that they should not do what they
are doing in the at_exit block.
OP can you give us the rationale behind this design. At first sight I
believe you
should do what you want in the main script. Look at Ara's ideas e.g.

Cheers
Robert


--=20
C'est v=E9ritablement utile puisque c'est joli.

Antoine de Saint Exup=E9ry

DMisener

9/22/2008 3:57:00 PM

0

On Sep 19, 6:57 am, Robert Dober <robert.do...@gmail.com> wrote:
> On Thu, Sep 18, 2008 at 10:07 PM, Robert Klemme> Oh, come on.  
> You can easily use that information to build what you want.

Actually inverting the logic isn't that easy (at least for me)

> Hmm maybe not Robert, my feeling is that they should not do what they
> are doing in the at_exit block.

I'm certainly not married to the the at_exit approach.

> OP can you give us the rationale behind this design. At first sight I
> believe you should do what you want in the main script. Look at Ara's ideas e.g.

Simple problem:

Create a tentative output working file. If the program exits
"cleanly" then rename the work file
to its "final" name. If not leave the work file for possible
examination.

Ideally this File.open_tentative_output_file would be plug
"compatible" with the simple File.open
(i.e. support modes and blocks).

Perhaps I'm trying to make life "too easy" for the application
programmer by eliminating the need for
an explicit File.close_all_pending_tentative_file routine. That is
really all that I am trying to achieve with the
at_exit{} code. One less step to remember. But perhaps the
implementation complexity isn't worth it.

BTW: It sure would be nice to have an on_abort{} handler.


ara.t.howard

9/22/2008 4:11:00 PM

0


On Sep 22, 2008, at 9:51 AM, DMisener wrote:

> BTW: It sure would be nice to have an on_abort{} handler.

there is : 'rescue'

a @ http://codeforp...
--
we can deny everything, except that we have the possibility of being
better. simply reflect on that.
h.h. the 14th dalai lama