Provided #dup generally returns an object of the same type, I would expect to have a Tempfile object.
The unexpected thing was that if I replay the same scenario with File, I have what I expect. I was just wondering whether the behaviour discrepancy between File and Tempfile was normal.
A Tempfile uses a finalizer to clean up the target file.
That is the file will be removed when a dup of Tempfile is discarded (and also will be tried to remove again).
I don't think it is a good idea to use Tempfile#dup.
What do you want to achieve by using this method?
Thanks nobu for your answer it makes perfect sense.
My case which led to the current question comes from a Rails application which has a controller receiving a file. My input params[:file] hold an ActionDispatch::Http::UploadedFile which itself has an attribute tempfile.
In the controller, params[:file] is passed to some functions (I don't have the control of) that can read and close the underlying tempfile. As a matter a fact, the code calls ActionDispatch::Http::UploadedFile#open (shortcut to tempfile#open) after the calls that close the file.
I was wondering whether I could avoid calling #open by providing the methods which can close the file with a duped file descriptor so that the original ActionDispatch::Http::UploadedFile is left untouched until I really use it in my own code.
The scenario in itself is not really interesting, it is just I was surprised by the behaviour when I used Tempfile#dup but your explanation is acceptable. Thanks for this.
Instead of storing the delegate in @tmpfile, use getobj, since
delegate library already handles dup/clone for that. Copy the
unlinked, mode, and opts instance variables to the returned object
when using dup/clone.
Split the close/unlink finalizer into two finalizers. The close
finalizer always closes when any Tempfile instance is GCed, since
each Tempfile instance uses a separate file descriptor. The unlink
finalizer unlinks only when the original and all duped/cloned
Tempfiles are GCed, since all share the same path.
For Tempfile#open, undefine the close finalizer after closing the
current file, the redefine the close finalizer with the new file.