From: DMisener Date: 2008-09-23T04:01:54+09:00 Subject: Re: at_exit handler *except* for fatal runtime error On Sep 22, 3:47 pm, Robert Klemme wrote: > On 22.09.2008 17:56, DMisener wrote: > > > > > On Sep 19, 6:57 am, Robert Dober 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. > > It rather seems that you're making *your* life too hard. :-) Probably... :-) > > >  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. > > Why do you need at_exit for this - especially if you want to be > compatible to File.open? > > def File.open_tentative_output_file(tmp, final, mode = "w", &b) >    raise "Need a block" unless b >    File.open(tmp, mode, &b) >    File.rename tmp, final > end So the recommendation is that any "successful program completion" cleanup be coerced into the execute a block then cleanup construct cited above. Enforcing the the block is required is the key. I was hoping to relax that requirement but you can't have everything. That might do the trick... BTW: here was my previous implementation... actually called OutputFile # Setup ABORT detection preamble $ABORTING=true def exit_program *args $ABORTING=false __original_exit__(*args) end .... alias :exit :exit_program class OutputFile def initialize filename,options={},&block @filename,@options,@block=filename.dup,options.dup,block @mode=options[:mode] || 'w' unless append? # TODO: Nice if we could validate valid filename here instead of at "open?" time # TODO: support :nosuperceed, :superceed File.send(@options[:backup] ? :backup : :delete,@filename) if File.exists? @filename @work_filename=Filename.work filename end if block_given? yield self close else # TODO: Support suppression of autoclose on fatal_error at_exit{close unless $ABORTING} end @file end def puts *args open? @file.puts(*args) end def print *args open? @file.puts(*args) end def close if @file @file.close # TODO: what to do if rename fails for any reason File.rename @work_filename,@filename if @work_filename end @file=nil end private def open? # Defer open until first require output request return if @file # TODO: support wait on busy @file=File.open(@work_filename || @filename,@mode) end def append? /a/i.match(@mode) end end def OutputFile *args,&block OutputFile.new(*args,&block) end