Project

General

Profile

Actions

Bug #19441

open

Closing an Tempfile#dup behaviour

Added by stac47 (Laurent Stacul) 8 months ago. Updated 6 months ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 3.2.1 (2023-02-08 revision 31819e82c8) [x86_64-darwin20]
[ruby-core:112445]

Description

Hello amazing ruby folks!

I classified that ticket as a "Bug" although it is perhaps something I did not understand.

Here is a ruby session:

irb(main):001:0> file = Tempfile.new
=> #<File:/var/folders/m2/bljzrgq160vbf0vk466k_7gw0000gn/T/20230216-39664-davfmj>
irb(main):002:0> file.fileno
=> 9
irb(main):003:0> dup = file.dup
=> #<File:/var/folders/m2/bljzrgq160vbf0vk466k_7gw0000gn/T/20230216-39664-davfmj>
irb(main):004:0> dup.fileno
=> 10
irb(main):005:0> dup.close
=> nil
irb(main):006:0> dup.closed?
=> false
irb(main):007:0> file.closed?
=> true

The two last lines are unexpected to me. I would have expected the converse:

irb(main):006:0> dup.closed?
=> true
irb(main):007:0> file.closed?
=> false

I tried this scenario in latest ruby but also in ruby 2.7.

Thanks in advance for helping me to understand this behaviour.

Updated by nobu (Nobuyoshi Nakada) 8 months ago

What do you expect for the dupped Tempfile object?
An IO to the same file?
Or another temporary file?

Updated by stac47 (Laurent Stacul) 8 months ago

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.

irb(main):001:0> file = File.new("a_file.txt", "w+")
=> #<File:a_file.txt>
irb(main):002:0> file.size
=> 0
irb(main):003:0> dup = file.dup
=> #<File:a_file.txt>
irb(main):004:0> dup.closed?
=> false
irb(main):005:0> file.closed?
=> false
irb(main):006:0> dup.close
=> nil
irb(main):007:0> dup.closed?
=> true
irb(main):008:0> file.closed?
=> false

Updated by nobu (Nobuyoshi Nakada) 8 months ago

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?

Actions #4

Updated by byroot (Jean Boussier) 8 months ago

  • Subject changed from Closing an IO#dup behaviour to Closing an Tempfile#dup behaviour

Updated by stac47 (Laurent Stacul) 8 months ago

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.

Updated by jeremyevans0 (Jeremy Evans) 6 months ago

I think this is a bug in Tempfile#{dup,clone} that we should fix. I submitted a pull request for it: https://github.com/ruby/tempfile/pull/17

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0