Skip to content

Commit

Permalink
FIX: Ensure Rack::Test::UploadedFile closes its tempfile file descrip…
Browse files Browse the repository at this point in the history
…tor on GC (rack#180)
  • Loading branch information
bsodmike authored and Alex Damian Negru committed Apr 5, 2021
1 parent 170446b commit 79e4f51
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ VERSION
*.rbc
*.swp
/.bundle
/.idea
11 changes: 11 additions & 0 deletions lib/rack/test/uploaded_file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ def initialize(path, content_type = "text/plain", binary = false)
@tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding)
@tempfile.binmode if binary

ObjectSpace.define_finalizer(self, self.class.finalize(@tempfile))

FileUtils.copy_file(path, @tempfile.path)
end

Expand All @@ -47,6 +49,15 @@ def respond_to?(method_name, include_private = false) #:nodoc:
@tempfile.respond_to?(method_name, include_private) || super
end

def self.finalize(file)
proc { actually_finalize file }
end

def self.actually_finalize(file)
file.close
file.unlink
end

end

end
Expand Down
31 changes: 31 additions & 0 deletions spec/rack/test/uploaded_file_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ def test_file_path
File.dirname(__FILE__) + "/../../fixtures/foo.txt"
end

it "returns an instance of `Rack::Test::UploadedFile`" do
uploaded_file = Rack::Test::UploadedFile.new(test_file_path)

expect(uploaded_file).to be_a(Rack::Test::UploadedFile)
end

it "responds to things that Tempfile responds to" do
uploaded_file = Rack::Test::UploadedFile.new(test_file_path)

Expand All @@ -26,4 +32,29 @@ def test_file_path

expect(File.extname(uploaded_file.path)).to eq(".txt")
end

context "it should call its destructor" do
it "calls the destructor" do
expect(Rack::Test::UploadedFile).to receive(:actually_finalize).at_least(:once)

if RUBY_PLATFORM == 'java'
require 'java'
java_import 'java.lang.System'

20.times do |i|
uploaded_file = Rack::Test::UploadedFile.new(test_file_path)

uploaded_file = nil

System.gc()
end
else
uploaded_file = Rack::Test::UploadedFile.new(test_file_path)

uploaded_file = nil

GC.start
end
end
end
end

0 comments on commit 79e4f51

Please sign in to comment.