about summary refs log tree commit homepage
path: root/lib
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2013-11-02 19:44:07 +0000
committerEric Wong <normalperson@yhbt.net>2013-11-02 21:21:28 +0000
commitb7f1d6d700ab759b316f5715533c061572c9ea7b (patch)
tree807dd28d1e7114de209c9d956f26440b01ec486e /lib
parent1b31f96631af819efc6c779d9e14b53bb7313730 (diff)
downloadyahns-b7f1d6d700ab759b316f5715533c061572c9ea7b.tar.gz
We must not directly close descriptors allocated by applications
themselves.  The only way we may close them is to issue
body.close on the response body.

A simple comparison we used before may not work because Rack
response bodies may be wrapped by middleware, so we use a
private subclass of File.
Diffstat (limited to 'lib')
-rw-r--r--lib/yahns/stream_file.rb9
1 files changed, 5 insertions, 4 deletions
diff --git a/lib/yahns/stream_file.rb b/lib/yahns/stream_file.rb
index a7f47ac..03dab45 100644
--- a/lib/yahns/stream_file.rb
+++ b/lib/yahns/stream_file.rb
@@ -6,6 +6,9 @@ require_relative 'wbuf_common'
 class Yahns::StreamFile # :nodoc:
   include Yahns::WbufCommon
 
+  # do not use this in your app (or any of our API)
+  NeedClose = Class.new(File) # :nodoc:
+
   def initialize(body, persist, offset, count)
     if body.respond_to?(:to_io)
       @tmpio = body.to_io
@@ -17,7 +20,7 @@ class Yahns::StreamFile # :nodoc:
       else
         retried = false
         begin
-          @tmpio = File.open(path)
+          @tmpio = NeedClose.open(path)
         rescue Errno::EMFILE, Errno::ENFILE
           raise if retried
           retried = true
@@ -35,9 +38,7 @@ class Yahns::StreamFile # :nodoc:
 
   # called by last wbuf_flush
   def wbuf_close(client)
-    if File === @tmpio && @tmpio != @body
-      @tmpio.close
-    end
+    @tmpio.close if NeedClose === @tmpio
     wbuf_close_common(client)
   end
 end