about summary refs log tree commit homepage
diff options
context:
space:
mode:
-rw-r--r--ext/http11/http11_parser.c47
-rw-r--r--lib/mongrel.rb29
-rw-r--r--lib/mongrel/debug.rb44
-rw-r--r--lib/mongrel/rails.rb47
4 files changed, 91 insertions, 76 deletions
diff --git a/ext/http11/http11_parser.c b/ext/http11/http11_parser.c
index 9b399f8..8343127 100644
--- a/ext/http11/http11_parser.c
+++ b/ext/http11/http11_parser.c
@@ -21,11 +21,11 @@
 /** Data **/
 
 #line 24 "ext/http11/http11_parser.c"
-static int http_parser_start = 0;
+static const int http_parser_start = 0;
 
-static int http_parser_first_final = 53;
+static const int http_parser_first_final = 53;
 
-static int http_parser_error = 1;
+static const int http_parser_error = 1;
 
 #line 118 "ext/http11/http11_parser.rl"
 
@@ -66,8 +66,7 @@ size_t http_parser_execute(http_parser *parser, const char *buffer, size_t len,
   
 #line 68 "ext/http11/http11_parser.c"
         {
-        p -= 1;
-        if ( ++p == pe )
+        if ( p == pe )
                 goto _out;
         switch ( cs )
         {
@@ -95,7 +94,7 @@ st2:
         if ( ++p == pe )
                 goto _out2;
 case 2:
-#line 99 "ext/http11/http11_parser.c"
+#line 98 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 32: goto tr17;
                 case 36: goto st34;
@@ -121,7 +120,7 @@ st3:
         if ( ++p == pe )
                 goto _out3;
 case 3:
-#line 125 "ext/http11/http11_parser.c"
+#line 124 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 42: goto tr10;
                 case 43: goto tr11;
@@ -145,7 +144,7 @@ st4:
         if ( ++p == pe )
                 goto _out4;
 case 4:
-#line 149 "ext/http11/http11_parser.c"
+#line 148 "ext/http11/http11_parser.c"
         if ( (*p) == 32 )
                 goto tr19;
         goto st1;
@@ -198,7 +197,7 @@ st5:
         if ( ++p == pe )
                 goto _out5;
 case 5:
-#line 202 "ext/http11/http11_parser.c"
+#line 201 "ext/http11/http11_parser.c"
         if ( (*p) == 72 )
                 goto tr3;
         goto st1;
@@ -210,7 +209,7 @@ st6:
         if ( ++p == pe )
                 goto _out6;
 case 6:
-#line 214 "ext/http11/http11_parser.c"
+#line 213 "ext/http11/http11_parser.c"
         if ( (*p) == 84 )
                 goto st7;
         goto st1;
@@ -286,7 +285,7 @@ st14:
         if ( ++p == pe )
                 goto _out14;
 case 14:
-#line 290 "ext/http11/http11_parser.c"
+#line 289 "ext/http11/http11_parser.c"
         if ( (*p) == 10 )
                 goto st15;
         goto st1;
@@ -338,7 +337,7 @@ st53:
         if ( ++p == pe )
                 goto _out53;
 case 53:
-#line 342 "ext/http11/http11_parser.c"
+#line 341 "ext/http11/http11_parser.c"
         goto st1;
 tr21:
 #line 23 "ext/http11/http11_parser.rl"
@@ -348,7 +347,7 @@ st17:
         if ( ++p == pe )
                 goto _out17;
 case 17:
-#line 352 "ext/http11/http11_parser.c"
+#line 351 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 33: goto st17;
                 case 58: goto tr16;
@@ -387,7 +386,7 @@ st18:
         if ( ++p == pe )
                 goto _out18;
 case 18:
-#line 391 "ext/http11/http11_parser.c"
+#line 390 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 13: goto tr36;
                 case 32: goto tr38;
@@ -401,7 +400,7 @@ st19:
         if ( ++p == pe )
                 goto _out19;
 case 19:
-#line 405 "ext/http11/http11_parser.c"
+#line 404 "ext/http11/http11_parser.c"
         if ( (*p) == 13 )
                 goto tr36;
         goto st19;
@@ -413,7 +412,7 @@ st20:
         if ( ++p == pe )
                 goto _out20;
 case 20:
-#line 417 "ext/http11/http11_parser.c"
+#line 416 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 43: goto st20;
                 case 58: goto st21;
@@ -438,7 +437,7 @@ st21:
         if ( ++p == pe )
                 goto _out21;
 case 21:
-#line 442 "ext/http11/http11_parser.c"
+#line 441 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 32: goto tr19;
                 case 37: goto st22;
@@ -486,7 +485,7 @@ st24:
         if ( ++p == pe )
                 goto _out24;
 case 24:
-#line 490 "ext/http11/http11_parser.c"
+#line 489 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 32: goto tr31;
                 case 37: goto st25;
@@ -539,7 +538,7 @@ st27:
         if ( ++p == pe )
                 goto _out27;
 case 27:
-#line 543 "ext/http11/http11_parser.c"
+#line 542 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 32: goto tr19;
                 case 37: goto st28;
@@ -591,7 +590,7 @@ st30:
         if ( ++p == pe )
                 goto _out30;
 case 30:
-#line 595 "ext/http11/http11_parser.c"
+#line 594 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 32: goto tr40;
                 case 37: goto tr41;
@@ -613,7 +612,7 @@ st31:
         if ( ++p == pe )
                 goto _out31;
 case 31:
-#line 617 "ext/http11/http11_parser.c"
+#line 616 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 32: goto tr28;
                 case 37: goto st32;
@@ -635,7 +634,7 @@ st32:
         if ( ++p == pe )
                 goto _out32;
 case 32:
-#line 639 "ext/http11/http11_parser.c"
+#line 638 "ext/http11/http11_parser.c"
         if ( (*p) < 65 ) {
                 if ( 48 <= (*p) && (*p) <= 57 )
                         goto st33;
@@ -1061,7 +1060,7 @@ case 52:
   if(parser->body_start) {
     /* final \r\n combo encountered so stop right here */
     
-#line 1065 "ext/http11/http11_parser.c"
+#line 1064 "ext/http11/http11_parser.c"
 #line 163 "ext/http11/http11_parser.rl"
     parser->nread++;
   }
@@ -1074,7 +1073,7 @@ int http_parser_finish(http_parser *parser)
   int cs = parser->cs;
 
   
-#line 1078 "ext/http11/http11_parser.c"
+#line 1077 "ext/http11/http11_parser.c"
 #line 174 "ext/http11/http11_parser.rl"
 
   parser->cs = cs;
diff --git a/lib/mongrel.rb b/lib/mongrel.rb
index ca4ea12..8d0c57c 100644
--- a/lib/mongrel.rb
+++ b/lib/mongrel.rb
@@ -228,15 +228,13 @@ module Mongrel
     def read_body(remain, total, dispatcher)
       begin
         # write the odd sized chunk first
-        remain -= @body.write(@socket.read(remain % Const::CHUNK_SIZE))
+
+        remain -= @body.write(read_socket(remain % Const::CHUNK_SIZE))
         dispatcher.request_progress(params, remain, total) if dispatcher
 
         # then stream out nothing but perfectly sized chunks
         until remain <= 0 or @socket.closed?
-          data = @socket.read(Const::CHUNK_SIZE)
-          # have to do it this way since @socket.eof? causes it to block
-          raise "Socket closed or read failure" if not data or data.length != Const::CHUNK_SIZE
-          remain -= @body.write(data)
+          remain -= @body.write(read_socket(Const::CHUNK_SIZE))
           # ASSUME: we are writing to a disk and these writes always write the requested amount
           dispatcher.request_progress(params, remain, total) if dispatcher
         end
@@ -250,6 +248,20 @@ module Mongrel
       end
     end
 
+    def read_socket(len)
+      if !@socket.closed?
+        data = @socket.read(len)
+        if !data
+          raise "Socket read return nil"
+        elsif data.length != len
+          raise "Socket read returned insufficient data: #{data.length}"
+        else
+          data
+        end
+      else
+        raise "Socket already closed when reading."
+      end
+    end
 
     # Performs URI escaping so that you can construct proper
     # query strings faster.  Use this rather than the cgi.rb
@@ -386,8 +398,9 @@ module Mongrel
       elsif @header_sent
         raise "You have already sent the request headers."
       else
-        @header.out.rewind
-        @body.rewind
+        @header.out.truncate(0)
+        @body.close
+        @body = StringIO.new
       end
     end
 
@@ -587,7 +600,7 @@ module Mongrel
           end
         end
       rescue EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::EINVAL,Errno::EBADF
-        # ignored
+        client.close rescue Object
       rescue HttpParserError
         if $mongrel_debug_client
           STDERR.puts "#{Time.now}: BAD CLIENT (#{params[Const::HTTP_X_FORWARDED_FOR] || client.peeraddr.last}): #$!"
diff --git a/lib/mongrel/debug.rb b/lib/mongrel/debug.rb
index 4746792..64a1a16 100644
--- a/lib/mongrel/debug.rb
+++ b/lib/mongrel/debug.rb
@@ -20,7 +20,7 @@ module MongrelDbg
     Dir.mkdir(log_dir) if not File.exist?(log_dir)
     @log_dir = log_dir
     $objects_out=open(File.join("log","mongrel_debug","objects.log"),"w")
-    $objects_out.puts "run,classname,last,count,delta"
+    $objects_out.puts "run,classname,last,count,delta,lenmean,lensd,lenmax"
     $objects_out.sync = true
     $last_stat = nil
     $run_count = 0
@@ -122,20 +122,40 @@ module RequestLog
     include Mongrel::HttpHandlerPlugin
 
     def process(request,response)
-      stats = Hash.new(0)
-      ObjectSpace.each_object {|o| stats[o.class] += 1}
-
-      stats.sort {|(k1,v1),(k2,v2)| v2 <=> v1}.each do |k,v|
-        if $last_stat
-          delta = v - $last_stat[k]
-          if v > 10 and delta != 0
-            $objects_out.printf "%d,%s,%d,%d,%d\n", $run_count, k, $last_stat[k], v, delta
+      begin
+        stats = Hash.new(0)
+        lengths = {}
+        ObjectSpace.each_object do |o|
+          begin
+            if o.respond_to? :length
+              len = o.length
+              lengths[o.class] ||= Stats.new(o.class)
+              lengths[o.class].sample(len)
+            end
+          rescue Object
+          end
+
+          stats[o.class] += 1
+        end
+
+        stats.sort {|(k1,v1),(k2,v2)| v2 <=> v1}.each do |k,v|
+          if $last_stat
+            delta = v - $last_stat[k]
+            if v > 10 and delta != 0
+              if lengths[k]
+                $objects_out.printf "%d,%s,%d,%d,%d,%f,%f,%f\n", $run_count, k, $last_stat[k], v, delta,lengths[k].mean,lengths[k].sd,lengths[k].max
+              else
+                $objects_out.printf "%d,%s,%d,%d,%d,,,\n", $run_count, k, $last_stat[k], v, delta
+              end
+            end
           end
         end
-      end
 
-      $run_count += 1
-      $last_stat = stats
+        $run_count += 1
+        $last_stat = stats
+      rescue Object
+        STDERR.puts "object.log ERROR: #$!"
+      end
     end
   end
 
diff --git a/lib/mongrel/rails.rb b/lib/mongrel/rails.rb
index c1a7043..5dcbf7f 100644
--- a/lib/mongrel/rails.rb
+++ b/lib/mongrel/rails.rb
@@ -6,10 +6,11 @@
 
 require 'mongrel'
 require 'cgi'
+require 'sync'
 
-class Mutex
+class Sync
   # modified to open the waiting list for reporting purposes
-  attr_accessor :waiting
+  attr_accessor :sync_waiting
 end
 
 module Mongrel
@@ -41,7 +42,7 @@ module Mongrel
 
       def initialize(dir, mime_map = {})
         @files = Mongrel::DirHandler.new(dir,false)
-        @guard = Mutex.new
+        @guard = Sync.new
         @tick = Time.now
 
         # register the requested mime types
@@ -75,11 +76,11 @@ module Mongrel
             # we don't want the output to be really final until we're out of the lock
             cgi.default_really_final = false
 
-            lock! request.params[Mongrel::Const::PATH_INFO]
+            log_threads_waiting_for(request.params["PATH_INFO"])
 
-            Dispatcher.dispatch(cgi, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, response.body)
-
-            unlock!
+            @guard.synchronize(:EX) {
+              Dispatcher.dispatch(cgi, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, response.body)
+            }
 
             # This finalizes the output using the proper HttpResponse way
             cgi.out("text/html",true) {""}
@@ -88,26 +89,13 @@ module Mongrel
           rescue Object => rails_error
             STDERR.puts "#{Time.now}: Error calling Dispatcher.dispatch #{rails_error.inspect}"
             STDERR.puts rails_error.backtrace.join("\n")
-          ensure
-            unlock!
           end
         end
       end
 
-      def lock!(path)
-        # ultra dangerous, but people are asking to kill themselves.  here's the Katana
-        log_threads_waiting_for path
-        @guard.lock unless ActionController::Base.allow_concurrency
-      end
-
-      def unlock!
-        log_threads_waiting_for "unlock"
-        @guard.unlock unless ActionController::Base.allow_concurrency
-      end
-
       def log_threads_waiting_for(event)
         if $mongrel_debug_client and (Time.now - @tick > 10)
-          STDERR.puts "#{Time.now}: #{@guard.waiting.length} threads waiting for #{event}."
+          STDERR.puts "#{Time.now}: #{@guard.sync_waiting.length} threads sync_waiting for #{event}, #{self.listener.workers.list.length} still active in mongrel."
           @tick = Time.now
         end
       end
@@ -116,13 +104,12 @@ module Mongrel
       # sometimes you get exceptions.  In that case just do a real restart.
       def reload!
         begin
-          lock! "RAILS RELOAD"
-          $".replace $orig_dollar_quote
-          GC.start
-          Dispatcher.reset_application!
-          ActionController::Routing::Routes.reload
-        ensure
-          unlock!
+          @guard.synchronize(:EX) {
+            $".replace $orig_dollar_quote
+            GC.start
+            Dispatcher.reset_application!
+            ActionController::Routing::Routes.reload
+          }
         end
       end
     end
@@ -173,10 +160,6 @@ module Mongrel
         require 'dispatcher'
         require 'mongrel/rails'
 
-        if ActionController::Base.allow_concurrency
-          log "[RAILS] ActionController::Base.allow_concurrency is true.  Wow, you're very brave."
-        end
-
         ActionController::AbstractRequest.relative_url_root = ops[:prefix] if ops[:prefix]
 
         @rails_handler = RailsHandler.new(ops[:docroot], ops[:mime])