tempfiles created by tmpfile removed at exit - can I change this easily?

G

Graham Nicholls

Hi, I think the subject says it all, really. I'm trying to debug a script
(I think I'd call it a script as it is replacing a bash script), and if I
give -d as an argument to the script, then I'd like the tempfile not to be
deleted on exit. Will I have to override the close method in tmpfile, or
is there an easier way, please?

Thanks
Graham Nicholls
 
R

Robert Klemme

Graham Nicholls said:
Hi, I think the subject says it all, really. I'm trying to debug a script
(I think I'd call it a script as it is replacing a bash script), and if I
give -d as an argument to the script, then I'd like the tempfile not to be
deleted on exit. Will I have to override the close method in tmpfile, or
is there an easier way, please?

Thanks
Graham Nicholls
--

The answer's always "Yes". Now, what's the question?

No, serious: overriding Tempfile#close won't help as that has no impact on
the file deletion. If it's just for debugging, you can just copy the temp
dir contents before the script terminates.

Alternatively you can try ObjectSpace.undefine_finalizer(tempfile) to
prevent deletion. I didn't test this, just looked at the source. But
chances are good that it works. :)

Kind regards

robert
 
A

Ara.T.Howard

Hi, I think the subject says it all, really. I'm trying to debug a script
(I think I'd call it a script as it is replacing a bash script), and if I
give -d as an argument to the script, then I'd like the tempfile not to be
deleted on exit. Will I have to override the close method in tmpfile, or is
there an easier way, please?

i would try not to mess with the interals of Tempfile (although you could
easily do it that way) and make a subclass with this behaviour, eg:

harp:~ > cat a.rb
require 'tempfile'

class Tmpfile < Tempfile
class << self; attr :litter, true; end
def initialize(*a,&b)
t = super
ObjectSpace::undefine_finalizer self if self.class.litter
t
end
end

Tmpfile::litter = ENV['DEBUG']
t = Tmpfile::new __FILE__
puts t.path

harp:~ > ruby a.rb
/tmp/a.rb11653.0

harp:~ > ls /tmp/a.rb11653.0
ls: /tmp/a.rb11653.0: No such file or directory

harp:~ > DEBUG=1 ruby a.rb
/tmp/a.rb11655.0

harp:~ > ls /tmp/a.rb11655.0
/tmp/a.rb11655.0

whatever solution you choose - you must basically undefine the finalizer
somehow.

regards.

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| When you do something, you should burn yourself completely, like a good
| bonfire, leaving no trace of yourself. --Shunryu Suzuki
===============================================================================
 
R

Robert Klemme

i would try not to mess with the interals of Tempfile (although you could
easily do it that way) and make a subclass with this behaviour, eg:

harp:~ > cat a.rb
require 'tempfile'

class Tmpfile < Tempfile
class << self; attr :litter, true; end
def initialize(*a,&b)
t = super
ObjectSpace::undefine_finalizer self if self.class.litter
t
end
end

What do you need that "t" for? IMHO it's completely superfluous. The
return value of initialize is always completely ignored.

Also from an aesthetical point of view, I'd expect the flag "litter" to
behave exactly the other way round: if litter is true throw it away; you
keep it if litter is true.
Tmpfile::litter = ENV['DEBUG']
t = Tmpfile::new __FILE__
puts t.path

harp:~ > ruby a.rb
/tmp/a.rb11653.0

harp:~ > ls /tmp/a.rb11653.0
ls: /tmp/a.rb11653.0: No such file or directory

harp:~ > DEBUG=1 ruby a.rb
/tmp/a.rb11655.0

harp:~ > ls /tmp/a.rb11655.0
/tmp/a.rb11655.0

whatever solution you choose - you must basically undefine the finalizer
somehow.

Yep.

Regards

robert
 
G

Graham Nicholls

Robert Klemme wrote:

No, serious: overriding Tempfile#close won't help as that has no impact on
the file deletion. If it's just for debugging, you can just copy the temp
dir contents before the script terminates.
Alternatively you can try ObjectSpace.undefine_finalizer(tempfile) to
prevent deletion. I didn't test this, just looked at the source. But
chances are good that it works. :)

Thanks - thats taught me about ObjectSpace, and finalizers, which presumably
run on object deletion, and hopefully it works, too!

Graham
 
A

Ara.T.Howard

What do you need that "t" for? IMHO it's completely superfluous.

i always use a clearly defined return value in my code as, at minimum,
doccumentation. when i glance at the above it's instantly clear to me (eg.
when re-reading this in six months) that i am doing nothing except removing
the finalizer from the instance and returning it. in general i find that the
magic ruby rule of returning value of the last statement bad to rely upon in
all but the most simply cases - but for the real reason see below:
The return value of initialize is always completely ignored.

that cannot be asserted:

harp:~ > cat a.rb
class A
def initialize
42
end
def reinit
p initialize
end
end

A::new.reinit

harp:~ > ruby a.rb
42

if you mean to say that 'the value of initialize is ignored by default for the
single case when it is called by the default Object#new method' then you are
correct. remember, initialize is simply a method called, in one single case,
to fill in blank objects - it's quite possible and acceptable to call it with
side effects from within the class, or from within subclasses.

in general i think it's poor practice to leave a method with a random return
value: one should return something meaningful and, if that's not possible,
return self to allow chaining.
Also from an aesthetical point of view, I'd expect the flag "litter" to
behave exactly the other way round: if litter is true throw it away; you
keep it if litter is true.

tempfiles are thrown away 'properly' in the normal case - eg. they do not
'litter' /tmp (a very dangerous practice). i would consider a program that
did not clean up after itself to have 'littered' - but it's of no matter:
change it if you like.

cheers.

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| When you do something, you should burn yourself completely, like a good
| bonfire, leaving no trace of yourself. --Shunryu Suzuki
===============================================================================
 
R

Robert Klemme

i always use a clearly defined return value in my code as, at minimum,
doccumentation. when i glance at the above it's instantly clear to me (eg.
when re-reading this in six months) that i am doing nothing except removing
the finalizer from the instance and returning it.

Well, but since you don't know what Tempfile#initialize returns (it's not
documented AFAIK) you can't deal with it properly anyway, can you?
in general i find that the
magic ruby rule of returning value of the last statement bad to rely upon in
all but the most simply cases - but for the real reason see below:


that cannot be asserted:

harp:~ > cat a.rb
class A
def initialize
42
end
def reinit
p initialize
end
end

A::new.reinit

harp:~ > ruby a.rb
42

if you mean to say that 'the value of initialize is ignored by default for the
single case when it is called by the default Object#new method' then you are
correct. remember, initialize is simply a method called, in one single case,
to fill in blank objects - it's quite possible and acceptable to call it with
side effects from within the class, or from within subclasses.

Didn't think of that. But still as #initialize's return value is
generally *not* used I'd rather not rely on that value. In your example
I'd have defined reinit like this - in concordance with your other
statement about return values :)

def reinit
initialize
self
end

in general i think it's poor practice to leave a method with a random return
value: one should return something meaningful and, if that's not possible,
return self to allow chaining.

Totally agree! Otherwise some internal state / instance might leak that
was never meant to be seen outside of the instance.
tempfiles are thrown away 'properly' in the normal case - eg. they do not
'litter' /tmp (a very dangerous practice). i would consider a program that
did not clean up after itself to have 'littered' - but it's of no matter:
change it if you like.

Ah, ok *now* I understand how you meant it. Sorry for the noise.

Kind regards

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top