Ticket #30: mongrel_changes.diff
| File mongrel_changes.diff, 29.4 kB (added by cmdrclueless, 4 months ago) |
|---|
-
lib/mongrel/configurator.rb
old new 136 136 opts[:throttle] ||= 0 137 137 opts[:timeout] ||= 60 138 138 139 @listener = Mongrel::HttpServer.new( 140 opts[:host], opts[:port].to_i, opts[:num_processors].to_i, 141 opts[:throttle].to_i, opts[:timeout].to_i, 142 opts[:log], opts[:log_level] 143 ) 139 if opts.has_key?(:unixmaster) and opts[:unixmaster] 140 @listener = Mongrel::UnixDispatchServer.new(opts[:host], 141 opts[:port], 142 opts[:min_children], 143 opts[:max_children], 144 opts[:log_file], 145 opts[:log_level]) 146 else 147 @listener = Mongrel::HttpServer.new(opts[:host], 148 opts[:port].to_i, 149 opts[:num_processors].to_i, 150 opts[:throttle].to_i, 151 opts[:timeout].to_i, 152 opts[:log_file], 153 opts[:log_level]) 154 end 144 155 @listener_name = "#{opts[:host]}:#{opts[:port]}" 145 156 @listeners[@listener_name] = @listener 146 157 … … 372 383 373 384 unless RUBY_PLATFORM =~ /djgpp|(cyg|ms|bcc)win|mingw/ 374 385 # graceful shutdown 375 trap("TERM") { Mongrel.log(:notice, " TERM signal received."); stop }386 trap("TERM") { Mongrel.log(:notice, "pid #{$$}: TERM signal received."); stop } 376 387 # debug mode 377 trap("USR1") { Mongrel.log(:notice, " USR1 received, toggling $mongrel_debug_client to #{!$mongrel_debug_client}"); $mongrel_debug_client = !$mongrel_debug_client }388 trap("USR1") { Mongrel.log(:notice, "pid #{$$}: USR1 received, toggling $mongrel_debug_client to #{!$mongrel_debug_client}"); $mongrel_debug_client = !$mongrel_debug_client } 378 389 # restart 379 trap("USR2") { Mongrel.log(:notice, " USR2 signal received."); stop(true) }390 trap("USR2") { Mongrel.log(:notice, "pid #{$$}: USR2 signal received."); stop(true) } 380 391 381 392 Mongrel.log(:notice, "Signals ready. TERM => stop. USR2 => restart. INT => stop (no restart).") 382 393 else … … 387 398 end 388 399 389 400 end 401 # vim:shiftwidth=2:tabstop=2:expandtab:ft=ruby -
lib/mongrel.rb
old new 1 # Copyright (c) 2005 Zed A. Shaw 2 # Copyright (c) 2008 Raritan Computer, Inc (Brian Weaver <brian.weaver@raritan.com>) 1 3 # Ruby 2 4 require 'socket' 3 5 require 'tempfile' … … 47 49 attr_accessor :http_body 48 50 end 49 51 50 # This is the main driver of Mongrel, while the Mongrel::HttpParser and Mongrel::URIClassifier 51 # make up the majority of how the server functions. It's a very simple class that just 52 # has a thread accepting connections and a simple HttpServer.process_client function 53 # to do the heavy lifting with the IO and Ruby. 54 # 55 # You use it by doing the following: 56 # 57 # server = 2("0.0.0.0", 3000) 58 # server.register("/stuff", MyNiftyHandler.new) 59 # server.run.join 60 # 61 # The last line can be just server.run if you don't want to join the thread used. 62 # If you don't though Ruby will mysteriously just exit on you. 63 # 64 # Ruby's thread implementation is "interesting" to say the least. Experiments with 65 # *many* different types of IO processing simply cannot make a dent in it. Future 66 # releases of Mongrel will find other creative ways to make threads faster, but don't 67 # hold your breath until Ruby 1.9 is actually finally useful. 68 class HttpServer 69 attr_reader :acceptor 70 attr_reader :workers 71 attr_reader :classifier 72 attr_reader :host 73 attr_reader :port 74 attr_reader :throttle 75 attr_reader :timeout 76 attr_reader :num_processors 77 52 class Server 78 53 attr_accessor :logger 54 attr_reader :acceptor 55 attr_accessor :classifier 56 attr_reader :domain 57 attr_reader :host 58 attr_reader :port 79 59 80 # Creates a working server on host:port (strange things happen if port isn't a Number). 81 # Use HttpServer::run to start the server and HttpServer.acceptor.join to 82 # join the thread that's processing incoming requests on the socket. 83 # 84 # The num_processors optional argument is the maximum number of concurrent 85 # processors to accept, anything over this is closed immediately to maintain 86 # server processing performance. This may seem mean but it is the most efficient 87 # way to deal with overload. Other schemes involve still parsing the client's request 88 # which defeats the point of an overload handling system. 89 # 90 # The throttle parameter is a sleep timeout (in hundredths of a second) that is placed between 91 # socket.accept calls in order to give the server a cheap throttle time. It defaults to 0 and 92 # actually if it is 0 then the sleep is not done at all. 93 def initialize(host, port, num_processors=950, throttle=0, timeout=60, log=nil, log_level=:debug) 94 95 tries = 0 96 @socket = TCPServer.new(host, port) 97 60 def initialize(log=nil, log_level=:debug) 98 61 @classifier = URIClassifier.new 99 @host = host 100 @port = port 101 @workers = ThreadGroup.new 102 @throttle = throttle 103 @num_processors = num_processors 104 @timeout = timeout 105 @logger = Mongrel::Log.new(log || "log/mongrel-#{host}-#{port}.log", log_level) 62 @logger = Mongrel::Log.new(log || "log/mongrel-#{domain}-#{host}-#{port}.log", log_level) 106 63 end 107 64 108 65 # Does the majority of the IO processing. It has been written in Ruby using … … 117 74 request = nil 118 75 data = client.readpartial(Const::CHUNK_SIZE) 119 76 nparsed = 0 120 77 121 78 # Assumption: nparsed will always be less since data will get filled with more 122 79 # after each parsing. If it doesn't get more then there was a problem 123 80 # with the read operation on the client socket. Effect is to stop processing when the … … 185 142 end 186 143 end 187 144 end 188 rescue EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::EINVAL,Errno::EBADF 145 rescue EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::EINVAL,Errno::EBADF => e 146 Mongrel.log(:debug, e.message) 189 147 client.close rescue nil 190 148 rescue HttpParserError => e 191 Mongrel.log(:error, " #{Time.now.httpdate}:HTTP parse error, malformed request (#{params[Const::HTTP_X_FORWARDED_FOR] || client.peeraddr.last}): #{e.inspect}")192 Mongrel.log(:error, " #{Time.now.httpdate}:REQUEST DATA: #{data.inspect}\n---\nPARAMS: #{params.inspect}\n---\n")149 Mongrel.log(:error, "HTTP parse error, malformed request (#{params[Const::HTTP_X_FORWARDED_FOR] || client.peeraddr.last}): #{e.inspect}") 150 Mongrel.log(:error, "REQUEST DATA: #{data.inspect}\n---\nPARAMS: #{params.inspect}\n---\n") 193 151 # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4 194 152 client.write(Const::ERROR_400_RESPONSE) 195 rescue Errno::EMFILE 153 rescue Errno::EMFILE => e 154 Mongrel.log(:debug, e.message) 196 155 reap_dead_workers('too many files') 197 156 rescue Object => e 198 Mongrel.log(:error, " #{Time.now.httpdate}:Read error: #{e.inspect}")157 Mongrel.log(:error, "Read error: #{e.inspect}") 199 158 Mongrel.log(:error, e.backtrace.join("\n")) 200 159 ensure 201 160 begin 202 161 client.close 203 rescue IOError 162 rescue IOError => e 163 Mongrel.log(:debug, e.message) 204 164 # Already closed 205 165 rescue Object => e 206 Mongrel.log(:error, " #{Time.now.httpdate}:Client error: #{e.inspect}")166 Mongrel.log(:error, "Client error: #{e.inspect}") 207 167 Mongrel.log(:error, e.backtrace.join("\n")) 208 168 end 209 169 request.body.delete if request and request.body.class == Tempfile 210 170 end 211 171 end 212 172 173 def reap_dead_workers(reason=nil) 174 # override in subclass! 175 end 176 177 def configure_socket_options 178 case RUBY_PLATFORM 179 when /linux/ 180 # 9 is currently TCP_DEFER_ACCEPT 181 $tcp_defer_accept_opts = [Socket::SOL_TCP, 9, 1] 182 $tcp_cork_opts = [Socket::SOL_TCP, 3, 1] 183 when /freebsd(([1-4]\..{1,2})|5\.[0-4])/ 184 # Do nothing, just closing a bug when freebsd <= 5.4 185 when /freebsd/ 186 # Use the HTTP accept filter if available. 187 # The struct made by pack() is defined in /usr/include/sys/socket.h as accept_filter_arg 188 unless `/sbin/sysctl -nq net.inet.accf.http`.empty? 189 $tcp_defer_accept_opts = [Socket::SOL_SOCKET, Socket::SO_ACCEPTFILTER, ['httpready', nil].pack('a16a240')] 190 end 191 end 192 end 193 194 # Runs the thing. It returns the thread used so you can "join" it. You can also 195 # access the HttpServer::acceptor attribute to get the thread later. 196 def run 197 raise RuntimeError, "This method must be overridden by a subclass" 198 end 199 200 # Simply registers a handler with the internal URIClassifier. When the URI is 201 # found in the prefix of a request then your handler's HttpHandler::process method 202 # is called. See Mongrel::URIClassifier#register for more information. 203 # 204 # If you set in_front=true then the passed in handler will be put in the front of the list 205 # for that particular URI. Otherwise it's placed at the end of the list. 206 def register(uri, handler, in_front=false) 207 begin 208 @classifier.register(uri, [handler]) 209 rescue URIClassifier::RegistrationError 210 handlers = @classifier.resolve(uri)[2] 211 method_name = in_front ? 'unshift' : 'push' 212 handlers.send(method_name, handler) 213 end 214 handler.listener = self 215 end 216 217 # Removes any handlers registered at the given URI. See Mongrel::URIClassifier#unregister 218 # for more information. Remember this removes them *all* so the entire 219 # processing chain goes away. 220 def unregister(uri) 221 @classifier.unregister(uri) 222 end 223 224 def stop(synchronous=false) 225 #Mongrel.log(:debug, "stop invoked for #{self.inspect}") 226 # this appears to get invoked once for each signal, but after 227 # the first signal the 'acceptor' appear to be nil. WTF? 228 return if @acceptor.nil? 229 @acceptor.raise(StopServer.new) 230 231 if synchronous 232 sleep(0.5) while @acceptor.alive? 233 end 234 end 235 236 end 237 238 # This is the main driver of Mongrel, while the Mongrel::HttpParser and Mongrel::URIClassifier 239 # make up the majority of how the server functions. It's a very simple class that just 240 # has a thread accepting connections and a simple HttpServer.process_client function 241 # to do the heavy lifting with the IO and Ruby. 242 # 243 # You use it by doing the following: 244 # 245 # server = 2("0.0.0.0", 3000) 246 # server.register("/stuff", MyNiftyHandler.new) 247 # server.run.join 248 # 249 # The last line can be just server.run if you don't want to join the thread used. 250 # If you don't though Ruby will mysteriously just exit on you. 251 # 252 # Ruby's thread implementation is "interesting" to say the least. Experiments with 253 # *many* different types of IO processing simply cannot make a dent in it. Future 254 # releases of Mongrel will find other creative ways to make threads faster, but don't 255 # hold your breath until Ruby 1.9 is actually finally useful. 256 class HttpServer < Server 257 attr_reader :workers 258 attr_reader :throttle 259 attr_reader :timeout 260 attr_reader :num_processors 261 262 # Creates a working server on host:port (strange things happen if port isn't a Number). 263 # Use HttpServer::run to start the server and HttpServer.acceptor.join to 264 # join the thread that's processing incoming requests on the socket. 265 # 266 # The num_processors optional argument is the maximum number of concurrent 267 # processors to accept, anything over this is closed immediately to maintain 268 # server processing performance. This may seem mean but it is the most efficient 269 # way to deal with overload. Other schemes involve still parsing the client's request 270 # which defeats the point of an overload handling system. 271 # 272 # The throttle parameter is a sleep timeout (in hundredths of a second) that is placed between 273 # socket.accept calls in order to give the server a cheap throttle time. It defaults to 0 and 274 # actually if it is 0 then the sleep is not done at all. 275 def initialize(host, port, num_processors=950, throttle=0, timeout=60, log=nil, log_level=:debug) 276 277 @host = host 278 @port = port 279 @domain = "tcp" 280 281 super(log, log_level) 282 283 @socket = TCPServer.new(host, port) 284 @workers = ThreadGroup.new 285 @throttle = throttle 286 @timeout = timeout 287 @num_processors = num_processors 288 289 end 290 213 291 # Used internally to kill off any worker threads that have taken too long 214 292 # to complete processing. Only called if there are too many processors 215 293 # currently servicing. It returns the count of workers still active 216 294 # after the reap is done. It only runs if there are workers to reap. 217 295 def reap_dead_workers(reason='unknown') 296 218 297 if @workers.list.length > 0 219 Mongrel.log(:error, "#{Time.now.httpdate}: Reaping #{@workers.list.length} threads for slow workers because of '#{reason}'") 220 error_msg = "#{Time.now.httpdate}: Mongrel timed out this thread: #{reason}" 298 299 Mongrel.log(:error, "Reaping #{@workers.list.length} threads for slow workers because of '#{reason}'") 300 error_msg = "Mongrel timed out this thread: #{reason}" 221 301 mark = Time.now 222 302 @workers.list.each do |worker| 223 303 worker[:started_on] = Time.now if not worker[:started_on] 224 304 225 305 if mark - worker[:started_on] > @timeout + @throttle 226 Mongrel.log(:error, " #{Time.now.httpdate}:Thread #{worker.inspect} is too old, killing.")306 Mongrel.log(:error, "Thread #{worker.inspect} is too old, killing.") 227 307 worker.raise(TimeoutError.new(error_msg)) 228 308 end 229 309 end 310 230 311 end 231 312 232 return@workers.list.length313 @workers.list.length 233 314 end 234 315 235 316 # Performs a wait on all the currently running threads and kills any that take … … 238 319 # that much longer. 239 320 def graceful_shutdown 240 321 while reap_dead_workers("shutdown") > 0 241 Mongrel.log(:error, " #{Time.now.httpdate}:Waiting for #{@workers.list.length} requests to finish, could take #{@timeout + @throttle} seconds.")322 Mongrel.log(:error, "Waiting for #{@workers.list.length} requests to finish, could take #{@timeout + @throttle} seconds.") 242 323 sleep @timeout / 10 243 324 end 244 325 end 245 326 246 def configure_socket_options247 case RUBY_PLATFORM248 when /linux/249 # 9 is currently TCP_DEFER_ACCEPT250 $tcp_defer_accept_opts = [Socket::SOL_TCP, 9, 1]251 $tcp_cork_opts = [Socket::SOL_TCP, 3, 1]252 when /freebsd(([1-4]\..{1,2})|5\.[0-4])/253 # Do nothing, just closing a bug when freebsd <= 5.4254 when /freebsd/255 # Use the HTTP accept filter if available.256 # The struct made by pack() is defined in /usr/include/sys/socket.h as accept_filter_arg257 unless `/sbin/sysctl -nq net.inet.accf.http`.empty?258 $tcp_defer_accept_opts = [Socket::SOL_SOCKET, Socket::SO_ACCEPTFILTER, ['httpready', nil].pack('a16a240')]259 end260 end261 end262 263 327 # Runs the thing. It returns the thread used so you can "join" it. You can also 264 328 # access the HttpServer::acceptor attribute to get the thread later. 265 329 def run … … 279 343 280 344 num_workers = @workers.list.length 281 345 if num_workers >= @num_processors 282 Mongrel.log(:error, " #{Time.now.httpdate}:Server overloaded with #{num_workers} processors (#@num_processors max). Dropping connection.")346 Mongrel.log(:error, "Server overloaded with #{num_workers} processors (#@num_processors max). Dropping connection.") 283 347 client.close rescue nil 284 348 reap_dead_workers("max processors") 285 349 else … … 301 365 # client closed the socket even before accept 302 366 client.close rescue nil 303 367 rescue Object => e 304 Mongrel.log(:error, " #{Time.now.httpdate}:Unhandled listen loop exception #{e.inspect}.")368 Mongrel.log(:error, "Unhandled listen loop exception #{e.inspect}.") 305 369 Mongrel.log(:error, e.backtrace.join("\n")) 306 370 end 307 371 end 308 372 graceful_shutdown 309 373 ensure 310 374 @socket.close 311 # Mongrel.log(:error, "#{Time.now.httpdate}: Closed socket.")312 375 end 313 376 end 314 377 315 return@acceptor378 @acceptor 316 379 end 380 end 317 381 318 # Simply registers a handler with the internal URIClassifier. When the URI is 319 # found in the prefix of a request then your handler's HttpHandler::process method 320 # is called. See Mongrel::URIClassifier#register for more information. 321 # 322 # If you set in_front=true then the passed in handler will be put in the front of the list 323 # for that particular URI. Otherwise it's placed at the end of the list. 324 def register(uri, handler, in_front=false) 325 begin 326 @classifier.register(uri, [handler]) 327 rescue URIClassifier::RegistrationError 328 handlers = @classifier.resolve(uri)[2] 329 method_name = in_front ? 'unshift' : 'push' 330 handlers.send(method_name, handler) 382 class UnixDispatchServer < Server 383 attr_reader :min_children 384 attr_reader :num_children 385 attr_reader :max_children 386 387 def initialize(host, port, min_children=5, max_children=nil, log=nil, log_level=:debug) 388 @host = '127.0.0.1' 389 @domain = 'unix' 390 @port = 'anonymous' 391 super(log, log_level) 392 393 @tcpsocket = TCPServer.new(host,port) 394 395 @terminate = false 396 @children = Hash.new 397 @busy = Hash.new 398 399 @min_children = min_children 400 @max_children = max_children 401 402 @close_on_fork = [@tcpsocket] 403 end 404 405 def runchild(server) 406 BasicSocket.do_not_reverse_lookup = true 407 configure_socket_options 408 409 Mongrel.log(:notice, "New child server started, process #{$$}") 410 @acceptor = Thread.new do 411 begin 412 while not @terminate 413 begin 414 server.write("READY #{$$}\n") 415 server.flush 416 417 client = server.recv_io(TCPSocket) # read the client's file descriptor from the server! 418 unless client.is_a?(IO) 419 Mongrel.log(:error, "Child doesn't know how to handle object #{client.class}: #{client.inspect}") 420 next 421 end 422 if client.respond_to?(:setsockopt) and defined?($tcp_cork_opts) and $tcp_cork_opts 423 client.setsockopt(*$tcp_cork_opts) rescue nil 424 end 425 426 process_client(client) 427 rescue StopServer 428 Mongrel.log(:debug, "server #{$$} received StopServer command") 429 @terminate = true 430 rescue Errno::ECONNABORTED 431 Mongrel.log(:debug, "server #{$$} connection aborted") 432 client.close rescue nil 433 rescue Errno::EPIPE 434 # server broke connection 435 Mongrel.log(:debug, "server #{$$} broken pipe") 436 @terminate = true 437 rescue Object => e 438 @terminte = true 439 Mongrel.log(:error, "Unhandled listen loop exception #{e.inspect}.") 440 Mongrel.log(:error, e.backtrace.join("\n")) 441 end 442 end 443 ensure 444 server.write("CLOSED #{$$}\n") rescue nil 445 server.close rescue nil 446 end 447 Mongrel.log(:notice, "child server stopped, process #{$$}") 331 448 end 332 handler.listener = self 449 450 @acceptor 333 451 end 334 452 335 # Removes any handlers registered at the given URI. See Mongrel::URIClassifier#unregister 336 # for more information. Remember this removes them *all* so the entire 337 # processing chain goes away. 338 def unregister(uri) 339 @classifier.unregister(uri) 453 def start_child 454 cio,sio = UNIXSocket::socketpair 455 pid = fork 456 if pid.nil? # child 457 @close_on_fork << sio 458 begin 459 @close_on_fork.each { |io| io.close rescue nil } 460 runchild(cio).join 461 Kernel.exit! 0 462 rescue StopServer 463 Kernel.exit! 0 464 rescue Object => e 465 Mongrel.log(:error, "Unhandled listen loop exception #{e.inspect}.") 466 Mongrel.log(:error, e.backtrace.join("\n")) 467 end 468 Kernel.exit! 1 469 end 470 cio.close rescue nil 471 @close_on_fork << sio 472 [pid,sio] 340 473 end 341 474 342 # Stops the acceptor thread and then causes the worker threads to finish 343 # off the request queue before finally exiting. 344 def stop(synchronous=false) 345 @acceptor.raise(StopServer.new) 475 def evict_child(pid) 476 if @children.has_key?(pid) 477 io = @children.delete(pid) 478 if io.respond_to?(:close) 479 io.close rescue nil 480 end 481 end 482 if @busy.has_key?(pid) 483 io = @busy.delete(pid) 484 if io.respond_to?(:close) 485 io.close rescue nil 486 end 487 end 488 begin 489 Process.kill("TERM", pid) 490 Process.waitpid(pid) 491 rescue Errno::ESRCH,Errno::ECHILD 492 # do nothing 493 rescue Object => e 494 Mongrel.log(:error, "Unhandled exception #{e.inspect}.") 495 Mongrel.log(:error, e.backtrace.join("\n")) 496 end 497 end 346 498 347 if synchronous 348 sleep(0.5) while @acceptor.alive? 499 def run 500 BasicSocket.do_not_reverse_lookup = true 501 configure_socket_options 502 503 # start up the necessary number of children 504 # 505 (0...@min_children).each do 506 pid, socket = start_child 507 @children[pid] = socket 508 @busy[pid] = true 349 509 end 510 511 @acceptor = Thread.new do 512 begin 513 while not @terminate 514 begin 515 @children.each_key do |pid| 516 begin 517 do_evict = false 518 do_evict = true if @children[pid].closed? or Process.waitpid(pid, Process::WNOHANG) 519 rescue Errno::ECHILD 520 do_evice = true 521 rescue Object => e 522 Mongrel.log(:error, "Unhandled exception #{e.inspect}.") 523 Mongrel.log(:error, e.backtrace.join("\n")) 524 end 525 526 evict_child(pid) if do_evict 527 end 528 529 readfds = [ @tcpsocket ] + @children.values 530 r,w,e = Kernel.select(readfds, nil, nil, 60) 531 532 # check to see if anyone wants to talk to us. If no one is talking 533 # and we have more than the necessary number of children then signal 534 # one to terminate. 535 # 536 evict_child(@children.keys.first) if (r.nil? or r.empty?) and @children.length > @min_children 537 next if r.nil? 538 539 # OK, someone is talking. Find out who and process the client. 540 # Delay the processing of the TCP server socket until all the children 541 # are finished. This allows a client to become available before processing 542 # the HTTP connection. 543 # 544 flag_http = false 545 r.each do |io| 546 if io == @tcpsocket # a new connection from apache or the outside world 547 flag_http = true # defer 548 else # one of the children 549 begin 550 msg = io.readline 551 msg.chomp! 552 if msg =~ /^READY\s+(\d+)$/ 553 pid = $1.to_i 554 if @busy[pid].respond_to?(:close) 555 @busy[pid].close rescue nil 556 end 557 @busy[pid] = false 558 elsif msg =~ /CLOSED\s+(\d+)/ 559 evict_child($1.to_i) 560 end 561 rescue EOFError => ex 562 Mongrel.log(:error,ex.message) 563 @children.each_key do |pid| 564 evict_child(pid) if @children[pid] == io 565 end 566 end 567 end 568 end 569 570 next unless flag_http 571 572 client = @tcpsocket.accept 573 @busy.each_pair do |pid,busy| 574 unless busy 575 io = @children[pid] 576 io.send_io(client) 577 io.flush 578 579 @busy[pid] = client 580 client = nil 581 break 582 end 583 end 584 585 if client and not @max_children.nil? and @max_children == @children.length 586 Mongrel.log(:error, "Maximum number of thread exceeded, closing request") 587 client.close rescue nil 588 client = nil 589 end 590 591 next unless client 592 593 Mongrel.log(:debug, "No avaialble child found, spinning up a new child") 594 595 # spin up a new one 596 # 597 pid, socket = start_child 598 @children[pid] = socket 599 socket.readline 600 socket.send_io(client) 601 socket.flush 602 @busy[pid] = client 603 604 rescue StopServer 605 @terminate = true 606 rescue Object => e 607 Mongrel.log(:error, "Unhandled listen loop exception #{e.inspect}.") 608 Mongrel.log(:error, e.backtrace.join("\n")) 609 end 610 end 611 ensure 612 @tcpsocket.close rescue nil 613 @children.each_key { |pid| evict_child(pid) } 614 end 615 end # end thread 616 617 @acceptor 350 618 end 351 352 619 end 353 620 end 354 621 … … 357 624 358 625 $LOAD_PATH.unshift 'projects/mongrel_experimental/lib/' 359 626 Mongrel::Gems.require 'mongrel_experimental', ">=#{Mongrel::Const::MONGREL_VERSION}" 627 628 # vim:expandtab:shiftwidth=2:tabstop=2 -
bin/mongrel_rails
old new 1 1 # Copyright (c) 2005 Zed A. Shaw 2 # Copyright (c) 2008 Raritan Computer, Inc (Brian Weaver <brian.weaver@raritan.com>) 2 3 # You can redistribute it and/or modify it under the same terms as Ruby. 3 4 # 4 5 # Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html … … 27 28 ['-p', '--port PORT', "Which port to bind to", :@port, 3000], 28 29 ['-a', '--address ADDR', "Address to bind to", :@address, "0.0.0.0"], 29 30 ['-l', '--log FILE', "Where to write log messages", :@log_file, "log/mongrel.log"], 31 ['-L', '--log-level (debug|notice|warn|info|error)', "The logging level", :@log_level, 'debug'], 30 32 ['-P', '--pid FILE', "Where to write the PID", :@pid_file, "log/mongrel.pid"], 31 33 ['-n', '--num-procs INT', "Number of processors active before clients denied", :@num_processors, 1024], 32 34 ['-o', '--timeout TIME', "Time to wait (in seconds) before killing a stalled thread", :@timeout, 60], … … 38 40 ['-C', '--config PATH', "Use a config file", :@config_file, nil], 39 41 ['-S', '--script PATH', "Load the given file as an extra config script", :@config_script, nil], 40 42 ['-G', '--generate PATH', "Generate a config file for use with -C", :@generate, nil], 43 ['-U', '--unixmaster', "Run the rails as a master-slave server", :@unixmaster, false], 44 ['-N', '--children COUNT', "The default number of unix slaves to start", :@min_children, 5], 45 ['-M', '--max-children COUNT', "The maximum number of unix slaves to start", :@max_children, nil], 41 46 ['', '--user USER', "User to run as", :@user, nil], 42 47 ['', '--group GROUP', "Group to run as", :@group, nil], 43 48 ['', '--prefix PATH', "URL prefix for Rails app", :@prefix, nil] … … 69 74 valid_user? @user if @user 70 75 valid_group? @group if @group 71 76 77 @log_level = @log_level.to_sym unless @log_level.nil? or @log_level.is_a?(Symbol) 78 72 79 return @valid 73 80 end 74 81 … … 95 102 Mongrel.log("Settings loaded from #{@config_file} (they override command line).") if @config_file 96 103 end 97 104 98 Mongrel.log("Starting Mongrel listening at #{defaults[:host]}:#{defaults[:port]}, further information can be found in log/mongrel-#{defaults[:host]}-#{defaults[:port]}.log")105 Mongrel.log("Starting Mongrel listening at #{defaults[:host]}:#{defaults[:port]}, further information can be found in #{defaults[:log_file]}") 99 106 100 107 listener do 101 108 mime = {} … … 180 187 181 188 def config_keys 182 189 @config_keys ||= 183 %w(address host port cwd log_file pid_file environment docroot mime_map daemon debug includes config_script num_processors num_procs timeout throttle user group prefix)190 %w(address host port cwd log_file log_level pid_file environment docroot mime_map daemon debug includes config_script num_processors num_procs timeout throttle user group prefix unixmaster min_children max_children) 184 191 end 185 192 186 193 def settings … … 282 289 if not Mongrel::Command::Registry.instance.run ARGV 283 290 exit 1 284 291 end 292 293 # vim:shiftwidth=2:tabstop=2:expandtab:ft=ruby
