From: "ara.t.howard" Date: 2008-09-19T01:58:13+09:00 Subject: Re: at_exit handler *except* for fatal runtime error 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://codeforpeople.com/ -- we can deny everything, except that we have the possibility of being better. simply reflect on that. h.h. the 14th dalai lama