Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #79 (closed defect: fixed)

Opened 6 years ago

Last modified 4 years ago

concurrent invocations of send_file

Reported by: hammett@gmail.com Assigned to: David
Priority: normal Milestone: 0.9
Component: ActionPack Version: 1.1.1
Severity: major Keywords:
Cc:

Description

When running the Webrick server, and multiple send_file are used, the server may lock or a few output happens on the console, instead of sending the contents to browser.

Change History

10/14/04 15:34:53 changed by ror@andreas-s.net

This does not only seem to be a send_file problem, I noticed similar behaviour with the webrick dispatcher under heavy load (ApacheBench).

10/14/04 15:49:56 changed by hammett@gmail.com

Yes, I've changed my application to use Apache Http with fastcgi (windows) and then the send_file (or the underlying http engine) send binary content incorrectly.

This is the correct content: HTTP/1.1 200 OK Date: Thu, 14 Oct 2004 19:28:16 GMT Server: Apache/2.0.52 (Win32) mod_fastcgi/2.4.2 Last-Modified: Thu, 14 Oct 2004 19:23:38 GMT ETag: "4e2e-1b4-3f5617c4" Accept-Ranges: bytes Content-Length: 436 Connection: close Content-Type: image/gif

GIF89aî¶⌡"DA~FC~GD~HE~IF~JG~KH~LI~MJ~NK~OL~PM~QN~RP~TR~VT~XV~ZX~\Z~\~`_~cb~fe~ih~lk~on~rr~vv~zz:6üδδ≡≤≥≈≈≈≈   !∙♦☺#,î¶♠╤ pH,à╚ñr╔l:ƒ╨ógJ¡Z»╪Θ'─φz┐α░xL.¢╧h«0╦nSAó╕|N»█∩°╝~╧∩ïBknéWp~åçêëèÇ↔âÄoèæÆôïüàâàöÜ¢£qîùÄÖ¥úñåƒáéóѽ¼uº¿m¬¡│½»░Y▓┤║£╢╖ä╗└ú╜╛U╣┴╟ S╞╚╬|╩╦═╧╘w╤─╙╒┌r╫╛┘█┌▌╖▀α╘Γ░Σσ╬τ¿ΘΩ╟î∟☺☻♥♦♠

▲@ê a☻à

▬.`╚áa♥ç(►#J£Φ;

And this is what is actually outputed:

HTTP/1.1 200 OK Date: Thu, 14 Oct 2004 19:31:07 GMT Server: Apache/2.0.52 (Win32) mod_fastcgi/2.4.2 Content-Transfer-Encoding: binary Pragma: no-cache Cache-Control: no-cache, must-revalidate Content-Disposition: inline; filename="image22-140-20.gif" Expires: Thu, 14 Oct 2004 19:31:10 GMT Set-Cookie: _session_id=2621adecb2cee84c; path=/ Last-Modified: Thu, 14 Oct 2004 19:23:38 GMT Content-Length: 436 Connection: close Content-Type: image/gif

GIF89aî¶⌡"DA~FC~GD~HE~IF~JG~KH~LI~MJ~NK~OL~PM~QN~RP~TR~VT~XV~ZX~\Z~\~`_~cb~fe~ih~lk~on~rr~vv~zz:6üδδ≡≤≥≈≈≈≈   !∙♦☺#,î¶♠╤ pH,à╚ñr╔l:ƒ╨ógJ¡Z»╪Θ'─φz┐α░xL.¢╧h«0╦nSAó╕|N»█∩°╝~╧∩ïBknéWp~åçêëèÇ↔âÄoèæÆôïüàâàöÜ¢£qîùÄÖ¥úñåƒáéóѽ¼uº¿m¬¡│½»░Y▓┤║£╢╖ä╗└ú╜╛U╣┴╟ S╞╚╬|╩╦═╧╘w╤─╙╒┌r╫╛┘█┌▌╖▀α╘Γ░Σσ╬τ¿ΘΩ╟î∟☺☻♥♦♠

▲@ê a☻à ▬.`╚áa♥ç(►#J£Φ;

10/23/04 23:50:30 changed by Oct

on win32, ruby 1.8.2 [2004-07-29]

replacing the send_file by

name="D:/me2.jpg"
      content = File.open(name,"rb")
      size = File.size(name)
      $stderr.puts "Read #{name} and got #{size} bytes for a #{File.size(name)} file"
      @headers["Content-Type"]="image/jpeg"
      @headers['Content-Transfer-Encoding'] = 'binary'
      @headers['Content-Disposition']= "inline"
      @headers['Content-Length']=size
      
      
      count = 0
      render_text do
        while buf = content.read(2048)
          count = count + buf.length
          $stderr.puts "Read #{count}/#{size} bytes"
          print buf
        end
      end

always make the file send fails everytime:

127.0.0.1 - - [24/Oct/2004:01:21:33 Paris, Madrid] "GET /gallery/get_image HTTP/
1.0" 200 3070
- -> /gallery/get_image
#<WEBrick::HTTPStatus::NotFound: `/gallery/get_image' not found.>
Read D:/me2.jpg and got 12701 bytes for a 12701 file
Read 2048/12701 bytes
Read 4096/12701 bytes
Read 6144/12701 bytes
Read 8192/12701 bytes
Read 10240/12701 bytes
Read 12288/12701 bytes
Read 12701/12701 bytes
127.0.0.1 - - [24/Oct/2004:01:22:04 Paris, Madrid] "GET /gallery/get_image HTTP/
1.0" 200 3070
- -> /gallery/get_image
[2004-10-24 01:22:10] ERROR Errno::EINVAL: Invalid argument
        C:/ruby/lib/ruby/1.8/webrick/httprequest.rb:307:in `gets'
        C:/ruby/lib/ruby/1.8/webrick/httprequest.rb:307:in `__send__'
        C:/ruby/lib/ruby/1.8/webrick/httprequest.rb:307:in `_read_data'
        C:/ruby/lib/ruby/1.8/webrick/httprequest.rb:306:in `timeout'
        C:/ruby/lib/ruby/1.8/timeout.rb:55:in `timeout'
        C:/ruby/lib/ruby/1.8/webrick/httprequest.rb:306:in `_read_data'
        C:/ruby/lib/ruby/1.8/webrick/httprequest.rb:317:in `read_line'
        C:/ruby/lib/ruby/1.8/webrick/httprequest.rb:207:in `read_request_line'
        C:/ruby/lib/ruby/1.8/webrick/httprequest.rb:80:in `parse'
        C:/ruby/lib/ruby/1.8/webrick/httpserver.rb:46:in `run'
        C:/ruby/lib/ruby/1.8/webrick/server.rb:150:in `start_thread'
        C:/ruby/lib/ruby/1.8/webrick/server.rb:144:in `start'
        C:/ruby/lib/ruby/1.8/webrick/server.rb:144:in `start_thread'
        C:/ruby/lib/ruby/1.8/webrick/server.rb:94:in `start'
        C:/ruby/lib/ruby/1.8/webrick/server.rb:89:in `each'
        C:/ruby/lib/ruby/1.8/webrick/server.rb:89:in `start'
        C:/ruby/lib/ruby/1.8/webrick/server.rb:79:in `start'
        C:/ruby/lib/ruby/1.8/webrick/server.rb:79:in `start'
        C:/ruby/lib/ruby/gems/1.8/gems/rails-0.7.0/lib/webrick_server.rb:17:in `
dispatch'
        public/dispatch.servlet:41

No concurrent call of send_file is needed to make this fail every time on this computer.

The Following code runs ok on the same computer (trying to send the whole file in Rails fails also):

require "webrick"

class Simple < WEBrick::HTTPServlet::AbstractServlet

  def do_GET(request, response)
    @headers = response.header
    @response=  response
    get_image
  end
  def render_text(text = nil, status = nil, &block) #:doc:
    @response.header["Status"] = 200
    @response.body = block_given? ? block : text
  end
  
def get_image
  name="D:/me2.jpg"
  content = File.open(name,"rb")
  size = File.size(name)
  $stderr.puts "Read #{name} and got #{size} bytes for a #{File.size(name)} file"
  @headers["Content-Type"]="image/jpeg"
  @headers["Content-Transfer-Encoding"] = "binary"
  @headers["Content-Disposition"]= "inline"
  @headers["Content-Length"]=size
  
  
  count = 0
  render_text content.read()
  end
  #send_file("D:/back2.jpg",
  #:type=>"image/jpeg",
  #:disposition=>"inline",
  #:buffer_size => 12000)
end
server = WEBrick::HTTPServer.new(:Port=>1224)
server.mount "/", Simple
trap "INT" do server.shutdown end

server.start

10/24/04 00:54:32 changed by hammett@gmail.com

So you're saying that this is really a Rails issue, and not WebBrick's? I suspected that. More probably the problem lies on the Rails binding for CGI/Webrick on Windows.

11/17/04 09:19:09 changed by bitsweat

  • milestone changed from 0.8 to 0.9.

Ticket #205 may help with the binmode issues.

11/17/04 16:10:25 changed by david

  • status changed from new to closed.
  • resolution set to fixed.

11/25/04 04:45:27 changed by anonymous

  • status changed from closed to reopened.
  • version changed from 0.7 to 0.8.
  • resolution deleted.
  • severity changed from normal to major.

I'm afraid this wasn't fixed. In fact things are worst as apache refuses to send file, logging

[Thu Nov 25 02:32:31 2004] [error] [client 127.0.0.1] malformed header from script. Bad header=\xff\xd8\xff\xe0: dispatch.cgi, referer: http://localhost:8080/projects/view/1 [Thu Nov 25 02:32:31 2004] [error] [client 127.0.0.1] malformed header from script. Bad header=\xff\xd8\xff\xe0: dispatch.cgi, referer: http://localhost:8080/projects/view/1

11/28/04 05:25:01 changed by sanehatter@gmail.com

I can verify this. I get the following errors after the ones mentioned by anonymous above:

[Sat Nov 27 21:22:12 2004] [error] [client 127.0.0.1] /usr/local/lib/ruby/gems/1.8/gems/actionpack-0.9.5.200411261554/lib/action_controller/base.rb:457: warning: syswrite for buffered IO

12/12/04 18:27:34 changed by david

  • status changed from reopened to closed.
  • resolution set to fixed.

Fixed in 0.9

12/06/05 11:22:24 changed by anonymous

  • status changed from closed to reopened.
  • resolution deleted.

12/06/05 18:43:48 changed by bitsweat

  • status changed from reopened to closed.
  • resolution set to fixed.

12/20/05 12:59:35 changed by philippe.langlois@gmail.com

Rails 0.13.1-2 exhibited the faulty behaviour.\\ With Rails 0.14.3-1, the faulty behaviour seems to have disappeared (fixed).\\ Note that I did no change on ruby itself (version 1.8.4).

My system is: Debian GNU/Linux testing/unstable

Fixed with:\\ root@localmachine:~# apt-get install rails

12/21/05 05:13:11 changed by Newhydra

  • status changed from closed to reopened.
  • version changed from 0.8 to 1.0.0.
  • resolution deleted.

Using 1.0 on linux with apache and I'm getting the same error about malformed headers.

06/14/06 15:02:59 changed by Pirmin Kalberer

  • version changed from 1.0.0 to 1.1.1.

The same problem here with Rails 1.1 and Apache 1.3 CGI A workaround is using :stream => false

11/09/06 09:21:00 changed by bitsweat

  • status changed from reopened to closed.
  • resolution set to fixed.

send_file no longer uses syswrite which may send data before the headers, which are sent with normal buffered io.