<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>experimentation/experiments/autoload1.rb</filename>
    </added>
    <added>
      <filename>experimentation/experiments/autoload2.rb</filename>
    </added>
    <added>
      <filename>experimentation/experiments/datamapper.rb</filename>
    </added>
    <added>
      <filename>experimentation/experiments/drb1.rb</filename>
    </added>
    <added>
      <filename>experimentation/experiments/drb2.rb</filename>
    </added>
    <added>
      <filename>experimentation/experiments/foo.rb</filename>
    </added>
    <added>
      <filename>experimentation/experiments/fork.rb</filename>
    </added>
    <added>
      <filename>experimentation/experiments/new_rake.rb</filename>
    </added>
    <added>
      <filename>experimentation/experiments/protected.rb</filename>
    </added>
    <added>
      <filename>experimentation/experiments/proxying.rb</filename>
    </added>
    <added>
      <filename>experimentation/experiments/rack.rb</filename>
    </added>
    <added>
      <filename>experimentation/experiments/rollback.rb</filename>
    </added>
    <added>
      <filename>experimentation/experiments/rollback2.rb</filename>
    </added>
    <added>
      <filename>experimentation/experiments/sorting_mimes.rb</filename>
    </added>
    <added>
      <filename>experimentation/simple_benches/haml.rb</filename>
    </added>
    <added>
      <filename>experimentation/simple_benches/instance_eval.rb</filename>
    </added>
    <added>
      <filename>experimentation/simple_benches/make_method.rb</filename>
    </added>
    <added>
      <filename>lib/merb-core/rack/adapter/abstract.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -36,6 +36,7 @@ module Merb
   module GlobalHelpers; end
   
   class &lt;&lt; self
+    attr_accessor :exiting
 
     # Merge environment settings
     # Can allow you to have a &quot;localdev&quot; that runs like your &quot;development&quot;
@@ -93,18 +94,24 @@ module Merb
     # argv&lt;String, Hash&gt;::
     #   The config arguments to start Merb with. Defaults to +ARGV+.
     def start(argv=ARGV)
+      # Hardcode the log stream to STDOUT
+      Merb::Config[:log_stream] = STDOUT
       if Hash === argv
         Merb::Config.setup(argv)
       else
         Merb::Config.parse_args(argv)
       end
+      Merb::Config[:log_stream] = STDOUT
+      
       Merb.environment = Merb::Config[:environment]
       Merb.root = Merb::Config[:merb_root]
       case Merb::Config[:action]
       when :kill
-        Merb::Server.kill(Merb::Config[:port], 1)
+        Merb::Server.kill(Merb::Config[:port], 2)
       when :kill_9
         Merb::Server.kill(Merb::Config[:port], 9)
+      when :fast_deploy
+        Merb::Server.kill(&quot;main&quot;, &quot;HUP&quot;)
       else
         Merb::Server.start(Merb::Config[:port], Merb::Config[:cluster])
       end
@@ -263,21 +270,43 @@ module Merb
     end
 
     # Logger settings
-    attr_accessor :logger
+    def logger
+      Thread.current[:merb_logger] ||= Merb::Logger.new
+    end
+
+    def logger=(obj)
+      unless obj
+        Thread.current[:merb_logger] = nil
+      end
+    end
 
     # ==== Returns
     # String::
     #   The path to the log file. If this Merb instance is running as a daemon
     #   this will return +STDOUT+.
-    def log_file
-      if Merb::Config[:log_file]
-        Merb::Config[:log_file]
-      elsif Merb.testing?
-        log_path / &quot;merb_test.log&quot;
-      elsif !(Merb::Config[:daemonize] || Merb::Config[:cluster])
-        STDOUT
-      else
-        log_path / &quot;merb.#{Merb::Config[:port]}.log&quot;
+    def log_stream(port = &quot;main&quot;)
+      @streams ||= {}
+      @streams[port] ||= begin
+        log = if Merb.testing?
+          log_path / &quot;merb_test.log&quot;
+        elsif !Merb::Config[:daemonize]
+          STDOUT
+        else
+          log_path / &quot;merb.#{port}.log&quot;
+        end        
+        
+        if log.is_a?(IO)
+          stream = log
+        elsif File.exist?(log)
+          stream = File.open(log, (File::WRONLY | File::APPEND))
+        else
+          FileUtils.mkdir_p(File.dirname(log))
+          stream = File.open(log, (File::WRONLY | File::APPEND | File::CREAT))
+          stream.write(&quot;#{Time.now.httpdate} #{Merb::Config[:log_delimiter]} &quot; \
+            &quot;info #{Merb::Config[:log_delimiter]} Logfile created\n&quot;)
+        end
+        stream.sync = true
+        stream
       end
     end
 
@@ -335,6 +364,28 @@ module Merb
         r.default_routes
       end
     end
+    
+    def fatal!(str, e = nil)
+      Merb.logger.fatal!
+      Merb.logger.fatal!(&quot;\e[1;31;47mFATAL: #{str}\e[0m&quot;)
+      Merb.logger.fatal!
+
+      print_colorized_backtrace(e) if e &amp;&amp; Merb::Config[:verbose]
+      exit(1)
+    end
+    
+    def print_colorized_backtrace(e)
+      e.backtrace.map! do |line|
+        line.gsub!(/^#{Merb.framework_root}/, &quot;\e[34mFRAMEWORK_ROOT\e[31m&quot;)
+      end
+      
+      Merb.logger.fatal! &quot;\e[34mFRAMEWORK_ROOT\e[0m = #{Merb.framework_root}&quot;
+      Merb.logger.fatal!
+      Merb.logger.fatal! &quot;\e[31m#{e.class}: \e[1;31;47m#{e.message}\e[0m&quot;
+      e.backtrace.each do |line|
+        Merb.logger.fatal! &quot;\e[31m#{line}\e[0m&quot;
+      end      
+    end
 
     # Set up default variables under Merb
     attr_accessor :klass_hashes, :orm, :test_framework, :template_engine</diff>
      <filename>lib/merb-core.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,7 +6,8 @@ module Merb
     #---
     # @semipublic
     cattr_accessor :subclasses, :after_load_callbacks, :before_load_callbacks, :finished
-    self.subclasses, self.after_load_callbacks, self.before_load_callbacks, self.finished = [], [], [], []
+    self.subclasses, self.after_load_callbacks, 
+      self.before_load_callbacks, self.finished = [], [], [], []
 
     class &lt;&lt; self
 
@@ -144,13 +145,23 @@ class Merb::BootLoader::Logger &lt; Merb::BootLoader
 
   # Sets Merb.logger to a new logger created based on the config settings.
   def self.run
-    Merb.logger = Merb::Logger.new(Merb.log_file, Merb::Config[:log_level], Merb::Config[:log_delimiter], Merb::Config[:log_auto_flush])
+    Merb::Config[:log_level] ||= begin
+      if Merb.environment == &quot;production&quot;
+        Merb::Logger::Levels[:warn]
+      else
+        Merb::Logger::Levels[:debug]
+      end          
+    end
+    
+    Merb::Config[:log_stream] = Merb.log_stream
+    
     print_warnings
   end
   
   def self.print_warnings
     if Gem::Version.new(Gem::RubyGemsVersion) &lt; Gem::Version.new(&quot;1.1&quot;)
-      Merb.logger.warn! &quot;Merb requires Rubygems 1.1 and later. Please upgrade RubyGems with gem update --system.&quot;
+      Merb.fatal! &quot;Merb requires Rubygems 1.1 and later. &quot; \
+        &quot;Please upgrade RubyGems with gem update --system.&quot;
     end
   end
 end
@@ -164,7 +175,7 @@ class Merb::BootLoader::DropPidFile &lt;  Merb::BootLoader
 
     # Stores a PID file if Merb is running daemonized or clustered.
     def run
-      Merb::Server.store_pid(Merb::Config[:port]) if Merb::Config[:daemonize] || Merb::Config[:cluster]
+      Merb::Server.store_pid(&quot;main&quot;) #if Merb::Config[:daemonize] || Merb::Config[:cluster]
     end
   end
 end
@@ -269,14 +280,17 @@ class Merb::BootLoader::Dependencies &lt; Merb::BootLoader
   end
 
   def self.enable_json_gem
+    gem &quot;json&quot;
     require &quot;json/ext&quot;
   rescue LoadError
+    gem &quot;json_pure&quot;
     require &quot;json/pure&quot;
   end
 
   def self.update_logger
-    updated_logger_options = [ Merb.log_file, Merb::Config[:log_level], Merb::Config[:log_delimiter], Merb::Config[:log_auto_flush] ]
-    Merb::BootLoader::Logger.run if updated_logger_options != Merb.logger.init_args
+    # Clear out the logger so that any changes in init.rb will be
+    # picked up
+    Merb.logger = nil
   end
 
   private
@@ -356,10 +370,24 @@ class Merb::BootLoader::LoadClasses &lt; Merb::BootLoader
     # Load all classes from Merb's native load paths.
     def run
       # Add models, controllers, helpers and lib to the load path
-      $LOAD_PATH.unshift Merb.dir_for(:model)
-      $LOAD_PATH.unshift Merb.dir_for(:controller)
-      $LOAD_PATH.unshift Merb.dir_for(:lib)
-      $LOAD_PATH.unshift Merb.dir_for(:helper)
+      unless @ran
+        $LOAD_PATH.unshift Merb.dir_for(:model)
+        $LOAD_PATH.unshift Merb.dir_for(:controller)
+        $LOAD_PATH.unshift Merb.dir_for(:lib)
+        $LOAD_PATH.unshift Merb.dir_for(:helper)
+      end
+
+      @ran = true
+      $0 = &quot;merb: master&quot;
+      
+      if Merb::Config[:fork_for_class_load] &amp;&amp; Merb.env != &quot;test&quot;
+        start_transaction
+      else
+        trap('INT') do 
+          Merb.logger.warn! &quot;Killing children&quot;
+          kill_children
+        end
+      end
 
       # Load application file if it exists - for flat applications
       load_file Merb.dir_for(:application) if File.file?(Merb.dir_for(:application))
@@ -373,13 +401,141 @@ class Merb::BootLoader::LoadClasses &lt; Merb::BootLoader
       Merb::Controller.send :include, Merb::GlobalHelpers
     end
     
+    # Wait for any children to exit, remove the &quot;main&quot; PID, and
+    # exit.
+    def exit_gracefully
+      Process.waitall
+      Merb::Server.remove_pid(&quot;main&quot;)
+      exit
+    end
+    
+    # If using fork-based code reloading, set up the BEGIN
+    # point and set up any signals in the parent and child.
+    def start_transaction
+      Merb.logger.warn! &quot;Parent pid: #{Process.pid}&quot;
+      reader, writer = nil, nil
+      
+      if GC.respond_to?(:copy_on_write_friendly=)
+        GC.copy_on_write_friendly = true
+      end      
+            
+      loop do
+        reader, @writer = IO.pipe
+        pid = Kernel.fork
+        
+        # pid means we're in the parent; only stay in the loop in that case
+        break unless pid
+        @writer.close
+
+        Merb::Server.store_pid(&quot;main&quot;)
+        
+        if Merb::Config[:console_trap]
+          trap(&quot;INT&quot;) {}
+        else
+          trap(&quot;INT&quot;) do 
+            Merb.logger.warn! &quot;Killing children&quot;
+            begin
+              Process.kill(&quot;ABRT&quot;, pid)
+            rescue SystemCallError
+            end
+            exit_gracefully
+          end
+        end
+        
+        trap(&quot;HUP&quot;) do 
+          Merb.logger.warn! &quot;Doing a fast deploy\n&quot;
+          Process.kill(&quot;HUP&quot;, pid)
+        end
+
+        reader_ary = [reader]
+        loop do
+          if exit_status = Process.wait2(pid, Process::WNOHANG)
+            exit_status[1] == 128 ? break : exit
+          end
+          if select(reader_ary, nil, nil, 0.25)
+            begin
+              next if reader.eof?
+              msg = reader.readline
+              if msg =~ /128/
+                break
+              else
+                exit_gracefully
+              end
+            rescue SystemCallError
+              exit_gracefully
+            end
+          end
+        end
+      end
+ 
+      reader.close
+ 
+      # add traps to the child
+      if Merb::Config[:console_trap]
+        Merb::Server.add_irb_trap
+        at_exit { kill_children }
+      else
+        trap('INT') {}
+        trap('ABRT') { kill_children }
+        trap('HUP') { kill_children(128) }
+      end
+    end
+    
+    # Kill any children of the spawner process and exit with
+    # an appropriate status code.
+    #
+    # Note that exiting the spawner process with a status code
+    # of 128 when a master process exists will cause the
+    # spawner process to be recreated, and the app code reloaded.
+    #
+    # @param status&lt;Integer&gt; The status code to exit with
+    def kill_children(status = 0)
+      Merb.exiting = true unless status == 128
+      
+      begin
+        @writer.puts(status.to_s) if @writer
+      rescue SystemCallError
+      end
+      
+      threads = []
+      
+      ($CHILDREN || []).each do |p|
+        threads &lt;&lt; Thread.new do
+          begin
+            Process.kill(&quot;ABRT&quot;, p)
+            Process.wait2(p)
+          rescue SystemCallError
+          end
+        end
+      end
+      threads.each {|t| t.join }
+      exit(status)
+    end
+    
     # ==== Parameters
     # file&lt;String&gt;:: The file to load.
     def load_file(file)
-      klasses = ObjectSpace.classes.dup
-      load file
-      LOADED_CLASSES[file] = ObjectSpace.classes - klasses
-      MTIMES[file] = File.mtime(file)
+      # Don't do this expensive operation unless we need to
+      unless Merb::Config[:fork_for_class_load]
+        klasses = ObjectSpace.classes.dup
+      end
+      
+      # Ignore the file for syntax errors. The next time
+      # the file is changed, it'll be reloaded again
+      begin
+        load file
+      rescue SyntaxError
+        return
+      ensure
+        if Merb::Config[:reload_classes]
+          MTIMES[file] = File.mtime(file)
+        end
+      end
+      
+      # Don't do this expensive operation unless we need to
+      unless Merb::Config[:fork_for_class_load]
+        LOADED_CLASSES[file] = ObjectSpace.classes - klasses
+      end
     end
     
     # Load classes from given paths - using path/glob pattern.
@@ -403,7 +559,11 @@ class Merb::BootLoader::LoadClasses &lt; Merb::BootLoader
     # ==== Parameters
     # file&lt;String&gt;:: The file to reload.
     def reload(file)
-      remove_classes_in_file(file) { |f| load_file(f) }
+      if !Merb::Config[:fork_for_class_load]
+        remove_classes_in_file(file) { |f| load_file(f) }
+      else
+        kill_children(128)
+      end
     end
     
     # Reload the router to regenerate all routes.
@@ -489,10 +649,11 @@ class Merb::BootLoader::LoadClasses &lt; Merb::BootLoader
         if klasses.size == size_at_start &amp;&amp; klasses.size != 0
           # Write all remaining failed classes and their exceptions to the log
           messages = error_map.only(*failed_classes).map do |klass, e|
-            [&quot;Could not load #{klass}:\n\n#{e.message} - (#{e.class})&quot;, &quot;#{(e.backtrace || []).join(&quot;\n&quot;)}&quot;]
+            [&quot;Could not load #{klass}:\n\n#{e.message} - (#{e.class})&quot;, 
+              &quot;#{(e.backtrace || []).join(&quot;\n&quot;)}&quot;]
           end
           messages.each { |msg, trace| Merb.logger.fatal!(&quot;#{msg}\n\n#{trace}&quot;) }
-          raise LoadError, &quot;#{messages[0][0]} (see log for details)&quot;
+          Merb.fatal! &quot;#{failed_classes.join(&quot;, &quot;)} failed to load.&quot;
         end
         break if(klasses.size == size_at_start || klasses.size == 0)
       end
@@ -681,7 +842,7 @@ class Merb::BootLoader::ReloadClasses &lt; Merb::BootLoader
       Thread.new do
         loop do
           sleep( seconds )
-          block.call
+          yield
         end
         Thread.exit
       end
@@ -692,26 +853,33 @@ class Merb::BootLoader::ReloadClasses &lt; Merb::BootLoader
   def self.run
     return unless Merb::Config[:reload_classes]
 
-    TimedExecutor.every(Merb::Config[:reload_time] || 0.5) do
-      reload
-    end
-    
-  end
-
-  # Reloads all files.
-  def self.reload
     paths = []
     Merb.load_paths.each do |path_name, file_info|
       path, glob = file_info
       next unless glob
       paths &lt;&lt; Dir[path / glob]
     end
+  
+    if Merb.dir_for(:application) &amp;&amp; File.file?(Merb.dir_for(:application))
+      paths &lt;&lt; Merb.dir_for(:application)
+    end
 
-    paths &lt;&lt; Merb.dir_for(:application) if Merb.dir_for(:application) &amp;&amp; File.file?(Merb.dir_for(:application))
+    paths.flatten!
 
-    paths.flatten.each do |file|
-      next if Merb::BootLoader::LoadClasses::MTIMES[file] &amp;&amp; Merb::BootLoader::LoadClasses::MTIMES[file] == File.mtime(file)
-      Merb::BootLoader::LoadClasses.reload(file)
+    TimedExecutor.every(Merb::Config[:reload_time] || 0.5) do
+      GC.start
+      reload(paths)
+    end
+    
+  end
+
+  # Reloads all files.
+  def self.reload(paths)
+    paths.each do |file|
+      next if LoadClasses::MTIMES[file] &amp;&amp;  
+        LoadClasses::MTIMES[file] == File.mtime(file)
+          
+      LoadClasses.reload(file)
     end
   end
 end</diff>
      <filename>lib/merb-core/bootloader.rb</filename>
    </modified>
    <modified>
      <diff>@@ -14,6 +14,7 @@ module Merb
           :port                   =&gt; &quot;4000&quot;,
           :adapter                =&gt; &quot;runner&quot;,
           :reload_classes         =&gt; true,
+          :fork_for_class_load    =&gt; !RUBY_PLATFORM.in?(&quot;windows&quot;, &quot;java&quot;),
           :environment            =&gt; &quot;development&quot;,
           :merb_root              =&gt; Dir.pwd,
           :use_mutex              =&gt; true,
@@ -102,6 +103,12 @@ module Merb
       #   Configuration settings to use. These are merged with the defaults.
       def setup(settings = {})
         @configuration = defaults.merge(settings)
+        
+        unless @configuration[:reload_classes]
+          @configuration[:fork_for_class_load] = false
+        end
+        
+        @configuration
       end
 
       # Parses the command line arguments and stores them in the config.
@@ -122,99 +129,158 @@ module Merb
 
           opts.banner = &quot;Usage: merb [uGdcIpPhmailLerkKX] [argument]&quot;
           opts.define_head &quot;Merb. Pocket rocket web framework&quot;
-          opts.separator '*'*80
-          opts.separator 'If no flags are given, Merb starts in the foreground on port 4000.'
-          opts.separator '*'*80
-
-          opts.on(&quot;-u&quot;, &quot;--user USER&quot;, &quot;This flag is for having merb run as a user other than the one currently logged in. Note: if you set this you must also provide a --group option for it to take effect.&quot;) do |user|
+          opts.separator '*' * 80
+          opts.separator &quot;If no flags are given, Merb starts in the &quot; \
+            &quot;foreground on port 4000.&quot;
+          opts.separator '*' * 80
+
+          opts.on(&quot;-u&quot;, &quot;--user USER&quot;, &quot;This flag is for having merb run &quot; \
+                  &quot;as a user other than the one currently logged in. Note: &quot; \
+                  &quot;if you set this you must also provide a --group option &quot; \
+                  &quot;for it to take effect.&quot;) do |user|
             options[:user] = user
           end
 
-          opts.on(&quot;-G&quot;, &quot;--group GROUP&quot;, &quot;This flag is for having merb run as a group other than the one currently logged in. Note: if you set this you must also provide a --user option for it to take effect.&quot;) do |group|
+          opts.on(&quot;-G&quot;, &quot;--group GROUP&quot;, &quot;This flag is for having merb run &quot; \
+                  &quot;as a group other than the one currently logged in. Note: &quot; \
+                  &quot;if you set this you must also provide a --user option &quot; \
+                  &quot;for it to take effect.&quot;) do |group|
             options[:group] = group
           end
 
-          opts.on(&quot;-d&quot;, &quot;--daemonize&quot;, &quot;This will run a single merb in the background.&quot;) do |daemon|
+          opts.on(&quot;-d&quot;, &quot;--daemonize&quot;, &quot;This will run a single merb in the &quot; \
+                  &quot;background.&quot;) do |daemon|
             options[:daemonize] = true
           end
+          
+          opts.on(&quot;-N&quot;, &quot;--no-daemonize&quot;, &quot;This will allow you to run a &quot; \
+                  &quot;cluster in console mode&quot;) do |no_daemon|
+            options[:daemonize] = false
+          end
 
-          opts.on(&quot;-c&quot;, &quot;--cluster-nodes NUM_MERBS&quot;, &quot;Number of merb daemons to run.&quot;) do |nodes|
+          opts.on(&quot;-c&quot;, &quot;--cluster-nodes NUM_MERBS&quot;, Integer, 
+                  &quot;Number of merb daemons to run.&quot;) do |nodes|
+            options[:daemonize] = true unless options.key?(:daemonize)
             options[:cluster] = nodes
           end
 
-          opts.on(&quot;-I&quot;, &quot;--init-file FILE&quot;, &quot;File to use for initialization on load, defaults to config/init.rb&quot;) do |init_file|
+          opts.on(&quot;-I&quot;, &quot;--init-file FILE&quot;, &quot;File to use for initialization &quot; \
+                  &quot;on load, defaults to config/init.rb&quot;) do |init_file|
             options[:init_file] = init_file
           end
 
-          opts.on(&quot;-p&quot;, &quot;--port PORTNUM&quot;, &quot;Port to run merb on, defaults to 4000.&quot;) do |port|
+          opts.on(&quot;-p&quot;, &quot;--port PORTNUM&quot;, Integer, &quot;Port to run merb on, &quot; \
+                  &quot;defaults to 4000.&quot;) do |port|
             options[:port] = port
           end
 
-          opts.on(&quot;-o&quot;, &quot;--socket-file FILE&quot;, &quot;Socket file to run merb on, defaults to [Merb.root]/log/merb.sock&quot;) do |port|
+          opts.on(&quot;-o&quot;, &quot;--socket-file FILE&quot;, &quot;Socket file to run merb on, &quot; \
+                  &quot;defaults to [Merb.root]/log/merb.sock. This is for &quot; \
+                  &quot;web servers, like thin, that use sockets.&quot;) do |port|
             options[:socket_file] = port
           end
 
-          opts.on(&quot;-s&quot;, &quot;--socket SOCKNUM&quot;, &quot;Socket number to run merb on, defaults to 0.&quot;) do |port|
+          opts.on(&quot;-s&quot;, &quot;--socket SOCKNUM&quot;, Integer, &quot;Socket number to run &quot; \
+                  &quot;merb on, defaults to 0.&quot;) do |port|
             options[:socket] = port
           end
 
-          opts.on(&quot;-P&quot;, &quot;--pid PIDFILE&quot;, &quot;PID file, defaults to [Merb.root]/log/merb.[port_number].pid&quot;) do |pid_file|
+          opts.on(&quot;-P&quot;, &quot;--pid PIDFILE&quot;, &quot;PID file, defaults to &quot; \
+                  &quot;[Merb.root]/log/merb.main.pid for the master process and&quot; \
+                  &quot;[Merb.root]/log/merb.[port number].pid for worker &quot; \
+                  &quot;processes. For clusters, use %s to specify where &quot; \
+                  &quot;in the file merb should place the port number. For &quot; \
+                  &quot;instance: -P myapp.%s.pid&quot;) do |pid_file|
             options[:pid_file] = pid_file
           end
 
-          opts.on(&quot;-h&quot;, &quot;--host HOSTNAME&quot;, &quot;Host to bind to (default is 0.0.0.0).&quot;) do |host|
+          opts.on(&quot;-h&quot;, &quot;--host HOSTNAME&quot;, &quot;Host to bind to &quot; \
+                  &quot;(default is 0.0.0.0).&quot;) do |host|
             options[:host] = host
           end
 
-          opts.on(&quot;-m&quot;, &quot;--merb-root /path/to/approot&quot;, &quot;The path to the Merb.root for the app you want to run (default is current working dir).&quot;) do |root|
+          opts.on(&quot;-m&quot;, &quot;--merb-root /path/to/approot&quot;, &quot;The path to the &quot; \
+                  &quot;Merb.root for the app you want to run &quot; \
+                  &quot;(default is current working directory).&quot;) do |root|
             options[:merb_root] = File.expand_path(root)
           end
 
-          opts.on(&quot;-a&quot;, &quot;--adapter mongrel&quot;, &quot;The rack adapter to use to run merb[mongrel, emongrel, thin, ebb, fastcgi, webrick, runner, irb]&quot;) do |adapter|
-            options[:adapter] = adapter
+          adapters = [:mongrel, :emongrel, :thin, :ebb, :fastcgi, :webrick]
+
+          opts.on(&quot;-a&quot;, &quot;--adapter ADAPTER&quot;,
+                  &quot;The rack adapter to use to run merb (default is mongrel)&quot; \
+                  &quot;[#{adapters.join(', ')}]&quot;) do |adapter|
+            options[:adapter] ||= adapter
           end
 
-          opts.on(&quot;-R&quot;, &quot;--rackup FILE&quot;, &quot;Load an alternate Rack config file (default is config/rack.rb)&quot;) do |rackup|
+          opts.on(&quot;-R&quot;, &quot;--rackup FILE&quot;, &quot;Load an alternate Rack config &quot; \
+                  &quot;file (default is config/rack.rb)&quot;) do |rackup|
             options[:rackup] = rackup
           end
 
-          opts.on(&quot;-i&quot;, &quot;--irb-console&quot;, &quot;This flag will start merb in irb console mode. All your models and other classes will be available for you in an irb session.&quot;) do |console|
+          opts.on(&quot;-i&quot;, &quot;--irb-console&quot;, &quot;This flag will start merb in &quot; \
+                  &quot;irb console mode. All your models and other classes will &quot; \
+                  &quot;be available for you in an irb session.&quot;) do |console|
             options[:adapter] = 'irb'
           end
 
-          opts.on(&quot;-S&quot;, &quot;--sandbox&quot;, &quot;This flag will enable a sandboxed irb console. If your ORM supports transactions, all edits will be rolled back on exit.&quot;) do |sandbox|
+          opts.on(&quot;-S&quot;, &quot;--sandbox&quot;, &quot;This flag will enable a sandboxed irb &quot; \
+                  &quot;console. If your ORM supports transactions, all edits will &quot; \
+                  &quot;be rolled back on exit.&quot;) do |sandbox|
             options[:sandbox] = true
           end
 
-          opts.on(&quot;-l&quot;, &quot;--log-level LEVEL&quot;, &quot;Log levels can be set to any of these options: debug &lt; info &lt; warn &lt; error &lt; fatal&quot;) do |log_level|
+          opts.on(&quot;-l&quot;, &quot;--log-level LEVEL&quot;, &quot;Log levels can be set to any of &quot; \
+                  &quot;these options: debug &lt; info &lt; warn &lt; error &lt; &quot; \
+                  &quot;fatal (default is info)&quot;) do |log_level|
             options[:log_level] = log_level.to_sym
           end
 
-          opts.on(&quot;-L&quot;, &quot;--log LOGFILE&quot;, &quot;A string representing the logfile to use.&quot;) do |log_file|
+          opts.on(&quot;-L&quot;, &quot;--log LOGFILE&quot;, &quot;A string representing the logfile to &quot; \
+                  &quot;use. Defaults to [Merb.root]/log/merb.[main].log for the &quot; \
+                  &quot;master process and [Merb.root]/log/merb[port number].log&quot; \
+                  &quot;for worker processes&quot;) do |log_file|
             options[:log_file] = log_file
           end
 
-          opts.on(&quot;-e&quot;, &quot;--environment STRING&quot;, &quot;Run merb in the correct mode(development, production, testing)&quot;) do |env|
+          opts.on(&quot;-e&quot;, &quot;--environment STRING&quot;, &quot;Environment to run Merb &quot; \
+                  &quot;under [development, production, testing] &quot; \
+                  &quot;(default is development)&quot;) do |env|
             options[:environment] = env
           end
 
           opts.on(&quot;-r&quot;, &quot;--script-runner ['RUBY CODE'| FULL_SCRIPT_PATH]&quot;,
-          &quot;Command-line option to run scripts and/or code in the merb app.&quot;) do |code_or_file|
+                  &quot;Command-line option to run scripts and/or code in the &quot; \
+                  &quot;merb app.&quot;) do |code_or_file|
             options[:runner_code] = code_or_file
             options[:adapter] = 'runner'
           end
 
-          opts.on(&quot;-K&quot;, &quot;--graceful PORT or all&quot;, &quot;Gracefully kill one merb proceses by port number.  Use merb -K all to gracefully kill all merbs.&quot;) do |ports|
+          opts.on(&quot;-K&quot;, &quot;--graceful PORT or all&quot;, &quot;Gracefully kill one &quot; \
+                  &quot;merb proceses by port number.  Use merb -K all to &quot; \
+                  &quot;gracefully kill all merbs.&quot;) do |ports|
             options[:action] = :kill
+            ports = &quot;main&quot; if ports == &quot;all&quot;
             options[:port] = ports
           end
 
-          opts.on(&quot;-k&quot;, &quot;--kill PORT or all&quot;, &quot;Kill one merb proceses by port number.  Use merb -k all to kill all merbs.&quot;) do |port|
+          opts.on(&quot;-k&quot;, &quot;--kill PORT&quot;, &quot;Force kill one merb worker &quot; \
+                  &quot;by port number. This will cause the worker to&quot; \
+                  &quot;be respawned. If you want to kill &quot;) do |port|
             options[:action] = :kill_9
+            port = &quot;main&quot; if port == &quot;all&quot;
             options[:port] = port
           end
+          
+          opts.on(&quot;--fast-deploy&quot;, &quot;Reload the code, but not your&quot; \
+            &quot;init.rb or gems&quot;) do
+              options[:action] = :fast_deploy
+          end
 
-          opts.on(&quot;-X&quot;, &quot;--mutex on/off&quot;, &quot;This flag is for turning the mutex lock on and off.&quot;) do |mutex|
+          # @todo Do we really need this flag? It seems unlikely to want to
+          #   change the mutex from the command-line.
+          opts.on(&quot;-X&quot;, &quot;--mutex on/off&quot;, &quot;This flag is for turning the &quot; \
+                  &quot;mutex lock on and off.&quot;) do |mutex|
             if mutex == &quot;off&quot;
               options[:use_mutex] = false
             else
@@ -226,10 +292,13 @@ module Merb
             begin
               require &quot;ruby-debug&quot;
               Debugger.start
-              Debugger.settings[:autoeval] = true if Debugger.respond_to?(:settings)
+              if Debugger.respond_to?(:settings)
+                Debugger.settings[:autoeval] = true
+              end
               puts &quot;Debugger enabled&quot;
             rescue LoadError
-              puts &quot;You need to install ruby-debug to run the server in debugging mode. With gems, use 'gem install ruby-debug'&quot;
+              puts &quot;You need to install ruby-debug to run the server in &quot; \
+                &quot;debugging mode. With gems, use `gem install ruby-debug'&quot;
               exit
             end
           end
@@ -249,7 +318,11 @@ module Merb
         end
 
         # Parse what we have on the command line
-        opts.parse!(argv)
+        begin
+          opts.parse!(argv)
+        rescue OptionParser::InvalidOption =&gt; e
+          Merb.fatal! e.message, e
+        end
         Merb::Config.setup(options)
       end
 </diff>
      <filename>lib/merb-core/config.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,203 +1,215 @@
-Merb::Logger = Extlib::Logger
+# Merb::Logger = Extlib::Logger
+
+class Merb::Logger &lt; Extlib::Logger
+  def verbose!(message, level = :warn)
+    send(&quot;#{level}!&quot;, message) if Merb::Config[:verbose]
+  end
+
+  def verbose(message, level = :warn)
+    send(level, message) if Merb::Config[:verbose]
+  end
+end
+
 # require &quot;time&quot; # httpdate
-# # ==== Public Merb Logger API
-# #
-# # To replace an existing logger with a new one:
-# #  Merb::Logger.set_log(log{String, IO},level{Symbol, String})
-# #
-# # Available logging levels are
-# #   Merb::Logger::{ Fatal, Error, Warn, Info, Debug }
-# #
-# # Logging via:
-# #   Merb.logger.fatal(message&lt;String&gt;,&amp;block)
-# #   Merb.logger.error(message&lt;String&gt;,&amp;block)
-# #   Merb.logger.warn(message&lt;String&gt;,&amp;block)
-# #   Merb.logger.info(message&lt;String&gt;,&amp;block)
-# #   Merb.logger.debug(message&lt;String&gt;,&amp;block)
-# #
-# # Logging with autoflush:
-# #   Merb.logger.fatal!(message&lt;String&gt;,&amp;block)
-# #   Merb.logger.error!(message&lt;String&gt;,&amp;block)
-# #   Merb.logger.warn!(message&lt;String&gt;,&amp;block)
-# #   Merb.logger.info!(message&lt;String&gt;,&amp;block)
-# #   Merb.logger.debug!(message&lt;String&gt;,&amp;block)
-# #
-# # Flush the buffer to 
-# #   Merb.logger.flush
-# #
-# # Remove the current log object
-# #   Merb.logger.close
-# # 
-# # ==== Private Merb Logger API
-# # 
-# # To initialize the logger you create a new object, proxies to set_log.
-# #   Merb::Logger.new(log{String, IO},level{Symbol, String})
-# module Merb
-# 
-#   class &lt;&lt; self
-#     attr_accessor :logger
-#   end
-# 
-#   class Logger
-# 
-#     attr_accessor :level
-#     attr_accessor :delimiter
-#     attr_accessor :auto_flush
-#     attr_reader   :buffer
-#     attr_reader   :log
-#     attr_reader   :init_args
-# 
-#     # ==== Notes
-#     # Ruby (standard) logger levels:
-#     # :fatal:: An unhandleable error that results in a program crash
-#     # :error:: A handleable error condition
-#     # :warn:: A warning
-#     # :info:: generic (useful) information about system operation
-#     # :debug:: low-level information for developers
-#     Levels = 
-#     {
-#       :fatal =&gt; 7, 
-#       :error =&gt; 6, 
-#       :warn  =&gt; 4,
-#       :info  =&gt; 3,
-#       :debug =&gt; 0
-#     } unless const_defined?(:Levels)
-# 
-#     private
-# 
-#     # Readies a log for writing.
-#     #
-#     # ==== Parameters
-#     # log&lt;IO, String&gt;:: Either an IO object or a name of a logfile.
-#     def initialize_log(log)
-#       close if @log # be sure that we don't leave open files laying around.
-# 
-#       if log.respond_to?(:write)
-#         @log = log
-#       elsif File.exist?(log)
-#         @log = open(log, (File::WRONLY | File::APPEND))
-#         @log.sync = true
-#       else
-#         FileUtils.mkdir_p(File.dirname(log)) unless File.directory?(File.dirname(log))
-#         @log = open(log, (File::WRONLY | File::APPEND | File::CREAT))
-#         @log.sync = true
-#         @log.write(&quot;#{Time.now.httpdate} #{delimiter} info #{delimiter} Logfile created\n&quot;)
-#       end
-#     end
-# 
-#     public
-# 
-#     # To initialize the logger you create a new object, proxies to set_log.
-#     #
-#     # ==== Parameters
-#     # *args:: Arguments to create the log from. See set_logs for specifics.
-#     def initialize(*args)
-#       @init_args = args
-#       set_log(*args)
-#     end
-# 
-#     # Replaces an existing logger with a new one.
-#     # 
-#     # ==== Parameters
-#     # log&lt;IO, String&gt;:: Either an IO object or a name of a logfile.
-#     # log_level&lt;~to_sym&gt;::
-#     #   The log level from, e.g. :fatal or :info. Defaults to :error in the
-#     #   production environment and :debug otherwise.
-#     # delimiter&lt;String&gt;::
-#     #   Delimiter to use between message sections. Defaults to &quot; ~ &quot;.
-#     # auto_flush&lt;Boolean&gt;::
-#     #   Whether the log should automatically flush after new messages are
-#     #   added. Defaults to false.
-#     def set_log(log, log_level = nil, delimiter = &quot; ~ &quot;, auto_flush = false)
-#       if log_level &amp;&amp; Levels[log_level.to_sym]
-#         @level = Levels[log_level.to_sym]
-#       elsif Merb.environment == &quot;production&quot;
-#         @level = Levels[:warn]
-#       else
-#         @level = Levels[:debug]
-#       end
-#       @buffer     = []
-#       @delimiter  = delimiter
-#       @auto_flush = auto_flush
-# 
-#       initialize_log(log)
-# 
-#       Merb.logger = self
-#     end
-# 
-#     # Flush the entire buffer to the log object.
-#     def flush
-#       return unless @buffer.size &gt; 0
-#       @log.write(@buffer.slice!(0..-1).to_s)
-#     end
-# 
-#     # Close and remove the current log object.
-#     def close
-#       flush
-#       @log.close if @log.respond_to?(:close) &amp;&amp; !@log.tty?
-#       @log = nil
-#     end
-# 
-#     # Appends a message to the log. The methods yield to an optional block and
-#     # the output of this block will be appended to the message.
-#     #
-#     # ==== Parameters
-#     # string&lt;String&gt;:: The message to be logged. Defaults to nil.
-#     #
-#     # ==== Returns
-#     # String:: The resulting message added to the log file.
-#     def &lt;&lt;(string = nil)
-#       message = &quot;&quot;
-#       message &lt;&lt; delimiter
-#       message &lt;&lt; string if string
-#       message &lt;&lt; &quot;\n&quot; unless message[-1] == ?\n
-#       @buffer &lt;&lt; message
-#       flush if @auto_flush
-# 
-#       message
-#     end
-#     alias :push :&lt;&lt;
-# 
-#     # Generate the logging methods for Merb.logger for each log level.
-#     Levels.each_pair do |name, number|
-#       class_eval &lt;&lt;-LEVELMETHODS, __FILE__, __LINE__
-# 
-#       # Appends a message to the log if the log level is at least as high as
-#       # the log level of the logger.
-#       #
-#       # ==== Parameters
-#       # string&lt;String&gt;:: The message to be logged. Defaults to nil.
-#       #
-#       # ==== Returns
-#       # self:: The logger object for chaining.
-#       def #{name}(message = nil)
-#         self &lt;&lt; message if #{number} &gt;= level
-#         self
-#       end
-# 
-#       # Appends a message to the log if the log level is at least as high as
-#       # the log level of the logger. The bang! version of the method also auto
-#       # flushes the log buffer to disk.
-#       #
-#       # ==== Parameters
-#       # string&lt;String&gt;:: The message to be logged. Defaults to nil.
-#       #
-#       # ==== Returns
-#       # self:: The logger object for chaining.
-#       def #{name}!(message = nil)
-#         self &lt;&lt; message if #{number} &gt;= level
-#         flush if #{number} &gt;= level
-#         self
-#       end
-# 
-#       # ==== Returns
-#       # Boolean:: True if this level will be logged by this logger.
-#       def #{name}?
-#         #{number} &gt;= level
-#       end
-#       LEVELMETHODS
-#     end
-# 
-#   end
-#   
-# end
+# ==== Public Merb Logger API
+#
+# To replace an existing logger with a new one:
+#  Merb::Logger.set_log(log{String, IO},level{Symbol, String})
+#
+# Available logging levels are
+#   Merb::Logger::{ Fatal, Error, Warn, Info, Debug }
+#
+# Logging via:
+#   Merb.logger.fatal(message&lt;String&gt;,&amp;block)
+#   Merb.logger.error(message&lt;String&gt;,&amp;block)
+#   Merb.logger.warn(message&lt;String&gt;,&amp;block)
+#   Merb.logger.info(message&lt;String&gt;,&amp;block)
+#   Merb.logger.debug(message&lt;String&gt;,&amp;block)
+#
+# Logging with autoflush:
+#   Merb.logger.fatal!(message&lt;String&gt;,&amp;block)
+#   Merb.logger.error!(message&lt;String&gt;,&amp;block)
+#   Merb.logger.warn!(message&lt;String&gt;,&amp;block)
+#   Merb.logger.info!(message&lt;String&gt;,&amp;block)
+#   Merb.logger.debug!(message&lt;String&gt;,&amp;block)
+#
+# Flush the buffer to 
+#   Merb.logger.flush
+#
+# Remove the current log object
+#   Merb.logger.close
+# 
+# ==== Private Merb Logger API
+# 
+# To initialize the logger you create a new object, proxies to set_log.
+#   Merb::Logger.new(log{String, IO},level{Symbol, String})
+module Merb
+
+  class Logger
+
+    attr_accessor :level
+    attr_accessor :delimiter
+    attr_accessor :auto_flush
+    attr_reader   :buffer
+    attr_reader   :log
+    attr_reader   :init_args
+
+    # ==== Notes
+    # Ruby (standard) logger levels:
+    # :fatal:: An unhandleable error that results in a program crash
+    # :error:: A handleable error condition
+    # :warn:: A warning
+    # :info:: generic (useful) information about system operation
+    # :debug:: low-level information for developers
+    Levels = 
+    {
+      :fatal =&gt; 7, 
+      :error =&gt; 6, 
+      :warn  =&gt; 4,
+      :info  =&gt; 3,
+      :debug =&gt; 0
+    } unless const_defined?(:Levels)
+
+    @@mutex = {}
+
+    private
+
+    # Readies a log for writing.
+    #
+    # ==== Parameters
+    # log&lt;IO, String&gt;:: Either an IO object or a name of a logfile.
+    def initialize_log(log)
+      close if @log # be sure that we don't leave open files laying around.
+
+      if log.respond_to?(:write)
+        @log = log
+      elsif File.exist?(log)
+        @log = open(log, (File::WRONLY | File::APPEND))
+        @log.sync = true
+      else
+        FileUtils.mkdir_p(File.dirname(log)) unless File.directory?(File.dirname(log))
+        @log = open(log, (File::WRONLY | File::APPEND | File::CREAT))
+        @log.sync = true
+        @log.write(&quot;#{Time.now.httpdate} #{delimiter} info #{delimiter} Logfile created\n&quot;)
+      end
+    end
+
+    public
+
+    # To initialize the logger you create a new object, proxies to set_log.
+    #
+    # ==== Parameters
+    # *args:: Arguments to create the log from. See set_logs for specifics.
+    def initialize(*args)
+      set_log(*args)
+    end
+
+    # Replaces an existing logger with a new one.
+    # 
+    # ==== Parameters
+    # log&lt;IO, String&gt;:: Either an IO object or a name of a logfile.
+    # log_level&lt;~to_sym&gt;::
+    #   The log level from, e.g. :fatal or :info. Defaults to :error in the
+    #   production environment and :debug otherwise.
+    # delimiter&lt;String&gt;::
+    #   Delimiter to use between message sections. Defaults to &quot; ~ &quot;.
+    # auto_flush&lt;Boolean&gt;::
+    #   Whether the log should automatically flush after new messages are
+    #   added. Defaults to false.
+    def set_log(stream = Merb::Config[:log_stream],
+      log_level = Merb::Config[:log_level], 
+      delimiter = Merb::Config[:log_delimiter], 
+      auto_flush = Merb::Config[:log_auto_flush])
+      
+      @buffer                   = []
+      @delimiter                = delimiter
+      @auto_flush               = auto_flush
+      
+      if Levels[log_level]
+        @level                  = Levels[log_level]
+      else
+        @level                  = log_level
+      end
+
+      @log                      = stream
+      @mutex = (@@mutex[@log] ||= Mutex.new)
+    end
+
+    # Flush the entire buffer to the log object.
+    def flush
+      return unless @buffer.size &gt; 0
+      @mutex.synchronize do
+        @log.write(@buffer.slice!(0..-1).to_s)
+      end
+    end
+
+    # Close and remove the current log object.
+    def close
+      flush
+      @log.close if @log.respond_to?(:close) &amp;&amp; !@log.tty?
+      @log = nil
+    end
+
+    # Appends a message to the log. The methods yield to an optional block and
+    # the output of this block will be appended to the message.
+    #
+    # ==== Parameters
+    # string&lt;String&gt;:: The message to be logged. Defaults to nil.
+    #
+    # ==== Returns
+    # String:: The resulting message added to the log file.
+    def &lt;&lt;(string = nil)
+      message = &quot;&quot;
+      message &lt;&lt; delimiter
+      message &lt;&lt; string if string
+      message &lt;&lt; &quot;\n&quot; unless message[-1] == ?\n
+      @buffer &lt;&lt; message
+      flush if @auto_flush
+
+      message
+    end
+    alias :push :&lt;&lt;
+
+    # Generate the logging methods for Merb.logger for each log level.
+    Levels.each_pair do |name, number|
+      class_eval &lt;&lt;-LEVELMETHODS, __FILE__, __LINE__
+
+      # Appends a message to the log if the log level is at least as high as
+      # the log level of the logger.
+      #
+      # ==== Parameters
+      # string&lt;String&gt;:: The message to be logged. Defaults to nil.
+      #
+      # ==== Returns
+      # self:: The logger object for chaining.
+      def #{name}(message = nil)
+        self &lt;&lt; message if #{number} &gt;= level
+        self
+      end
+
+      # Appends a message to the log if the log level is at least as high as
+      # the log level of the logger. The bang! version of the method also auto
+      # flushes the log buffer to disk.
+      #
+      # ==== Parameters
+      # string&lt;String&gt;:: The message to be logged. Defaults to nil.
+      #
+      # ==== Returns
+      # self:: The logger object for chaining.
+      def #{name}!(message = nil)
+        self &lt;&lt; message if #{number} &gt;= level
+        flush if #{number} &gt;= level
+        self
+      end
+
+      # ==== Returns
+      # Boolean:: True if this level will be logged by this logger.
+      def #{name}?
+        #{number} &gt;= level
+      end
+      LEVELMETHODS
+    end
+
+  end
+  
+end</diff>
      <filename>lib/merb-core/logger.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,6 +3,7 @@ module Merb
   module Rack
     autoload :Application,         'merb-core/rack/application'
     autoload :Adapter,             'merb-core/rack/adapter'
+    autoload :AbstractAdapter,     'merb-core/rack/adapter/abstract'
     autoload :Ebb,                 'merb-core/rack/adapter/ebb'
     autoload :EventedMongrel,      'merb-core/rack/adapter/evented_mongrel'    
     autoload :FastCGI,             'merb-core/rack/adapter/fcgi'</diff>
      <filename>lib/merb-core/rack.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,7 +11,11 @@ module Merb
         # ==== Returns.
         # Class:: The adapter class.
         def get(id)
-          Object.full_const_get(@adapters[id])
+          if @adapters[id.to_s]
+            Object.full_const_get(@adapters[id.to_s])
+          else
+            Merb.fatal! &quot;The adapter #{id} did not exist&quot;
+          end
         end
 
         # Registers a new Rack adapter.
@@ -36,9 +40,8 @@ module Merb
     Adapter.register %w{runner},         :Runner
     Adapter.register %w{smongrel swift}, :SwiftipliedMongrel
     Adapter.register %w{thin},           :Thin
-    Adapter.register %w{thin-turbo},     :ThinTurbo
+    Adapter.register %w{thin-turbo tt},  :ThinTurbo
     Adapter.register %w{webrick},        :WEBrick
     
   end # Rack
-end # Merb
-
+end # Merb
\ No newline at end of file</diff>
      <filename>lib/merb-core/rack/adapter.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,22 +3,21 @@ module Merb
   
   module Rack
 
-    class Ebb
+    class Ebb &lt; Merb::Rack::AbstractAdapter
       # start an Ebb server on given host and port.
       
-      # ==== Parameters
-      # opts&lt;Hash&gt;:: Options for Ebb (see below).
-      #
-      # ==== Options (opts)
-      # :host&lt;String&gt;:: The hostname that Ebb should serve.
-      # :port&lt;Fixnum&gt;:: The port Ebb should bind to.
-      # :app:: The application
-      def self.start(opts={})
-        Merb.logger.warn!(&quot;Using Ebb adapter&quot;)
+      def self.new_server(port)
         Merb::Dispatcher.use_mutex = false
-        th = Thread.new { ::Ebb.start_server(opts[:app], opts) }
-        Merb::Server.change_privilege
-        th.join
+        opts = @opts.merge(:port =&gt; port)
+        @th = Thread.new { Thread.current[:server] = ::Ebb.start_server(opts[:app], opts) }
+      end
+      
+      def self.start_server
+        @th.join
+      end
+      
+      def self.stop(status = 0)
+        ::Ebb.stop_server
       end
     end
   end</diff>
      <filename>lib/merb-core/rack/adapter/ebb.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,22 +4,9 @@ module Merb
   module Rack
 
     class EventedMongrel &lt; Mongrel
-      # Starts Mongrel as evented.
-      #
-      # ==== Parameters
-      # opts&lt;Hash&gt;:: Options for Mongrel (see below).
-      #
-      # ==== Options (opts)
-      # :host&lt;String&gt;:: The hostname that Mongrel should serve.
-      # :port&lt;Fixnum&gt;:: The port Mongrel should bind to.
-      # :app&lt;String&gt;&gt;:: The application name.
-      def self.start(opts={})
-        Merb.logger.warn!(&quot;Using EventedMongrel adapter&quot;)
+      def self.new_server(port)
         Merb::Dispatcher.use_mutex = false
-        server = ::Mongrel::HttpServer.new(opts[:host], opts[:port].to_i)
-        Merb::Server.change_privilege
-        server.register('/', ::Merb::Rack::Handler::Mongrel.new(opts[:app]))
-        server.run.join
+        super
       end
     end
   end</diff>
      <filename>lib/merb-core/rack/adapter/evented_mongrel.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,23 +4,30 @@ module Merb
 
   module Rack
 
-    class Mongrel
-      # start server on given host and port.
+    class Mongrel &lt; Merb::Rack::AbstractAdapter
+
+      def self.stop(status = 0)
+        if @server
+          begin
+            @server.stop(true)
+          rescue Mongrel::TimeoutError
+            Merb.logger.fatal! &quot;Your process took too long to shut &quot; \
+              &quot;down, so mongrel killed it.&quot;
+          end
+          true
+        end
+      end
       
-      # ==== Parameters
-      # opts&lt;Hash&gt;:: Options for Mongrel (see below).
-      #
-      # ==== Options (opts)
-      # :host&lt;String&gt;:: The hostname that Mongrel should serve.
-      # :port&lt;Fixnum&gt;:: The port Mongrel should bind to.
-      # :app&lt;String&gt;&gt;:: The application name.
-      def self.start(opts={})
-        Merb.logger.warn!(&quot;Using Mongrel adapter&quot;)
-        server = ::Mongrel::HttpServer.new(opts[:host], opts[:port].to_i)
-        Merb::Server.change_privilege
-        server.register('/', ::Merb::Rack::Handler::Mongrel.new(opts[:app]))
-        server.run.join
+      def self.new_server(port)
+        @server = ::Mongrel::HttpServer.new(@opts[:host], port)
       end
+      
+      def self.start_server
+        @server.register('/', ::Merb::Rack::Handler::Mongrel.new(@opts[:app]))
+        @server.run.join
+      end
+      
     end
+    
   end
 end
\ No newline at end of file</diff>
      <filename>lib/merb-core/rack/adapter/mongrel.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,23 +4,11 @@ module Merb
   module Rack
 
     class SwiftipliedMongrel &lt; Mongrel
-      # Starts Mongrel as swift.
-      #
-      # ==== Parameters
-      # opts&lt;Hash&gt;:: Options for Mongrel (see below).
-      #
-      # ==== Options (opts)
-      # :host&lt;String&gt;:: The hostname that Mongrel should serve.
-      # :port&lt;Fixnum&gt;:: The port Mongrel should bind to.
-      # :app&lt;String&gt;&gt;:: The application name.
-      def self.start(opts={})
-        Merb.logger.warn!(&quot;Using SwiftipliedMongrel adapter&quot;)
+      def self.new_server(port)
         Merb::Dispatcher.use_mutex = false
-        server = ::Mongrel::HttpServer.new(opts[:host], opts[:port].to_i)
-        Merb::Server.change_privilege
-        server.register('/', ::Merb::Rack::Handler::Mongrel.new(opts[:app]))
-        server.run.join
-      end
+        super
+      end      
     end
+    
   end
 end
\ No newline at end of file</diff>
      <filename>lib/merb-core/rack/adapter/swiftiplied_mongrel.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,35 +4,36 @@ module Merb
 
   module Rack
 
-    class Thin
+    class Thin &lt; Merb::Rack::AbstractAdapter
       # start a Thin server on given host and port.
 
-      # ==== Parameters
-      # opts&lt;Hash&gt;:: Options for Thin (see below).
-      #
-      # ==== Options (opts)
-      # :host&lt;String&gt;:: The hostname that Thin should serve.
-      # :port&lt;Fixnum&gt;:: The port Thin should bind to.
-      # :socket&lt;Fixnum&gt;&gt;:: The socket number that thin should bind to.
-      # :socket_file&lt;String&gt;&gt;:: The socket file that thin should attach to.
-      # :app&lt;String&gt;&gt;:: The application name.
-      def self.start(opts={})
+      def self.new_server(port)
         Merb::Dispatcher.use_mutex = false
-        if opts[:socket] || opts[:socket_file]
-          socket = opts[:socket] || &quot;0&quot;
-          socket_file = opts[:socket_file] || &quot;#{Merb.root}/log/merb.#{socket}.sock&quot;
+        
+        if @opts[:socket] || @opts[:socket_file]
+          socket = port.to_s
+          socket_file = @opts[:socket_file] || &quot;#{Merb.root}/log/merb.#{socket}.sock&quot;
           Merb.logger.warn!(&quot;Using Thin adapter with socket file #{socket_file}.&quot;)
-          server = ::Thin::Server.new(socket_file, opts[:app], opts)
+          @server = ::Thin::Server.new(socket_file, @opts[:app], @opts)
         else
-          Merb.logger.warn!(&quot;Using Thin adapter on host #{opts[:host]} and port #{opts[:port]}.&quot;)
-          if opts[:host].include?('/')
-            opts[:host] = &quot;#{opts[:host]}-#{opts[:port]}&quot;
+          Merb.logger.warn!(&quot;Using Thin adapter on host #{@opts[:host]} and port #{port}.&quot;)
+          if @opts[:host].include?('/')
+            @opts[:host] = &quot;#{@opts[:host]}-#{port}&quot;
           end
-          server = ::Thin::Server.new(opts[:host], opts[:port].to_i, opts[:app], opts)
+          @server = ::Thin::Server.new(@opts[:host], port, @opts[:app], @opts)
         end
-        Merb::Server.change_privilege
+      end
+
+      def self.start_server
         ::Thin::Logging.silent = true
-        server.start
+        @server.start
+      end
+      
+      def self.stop(status = 0)
+        if @server
+          @server.stop
+          true
+        end
       end
     end
   end</diff>
      <filename>lib/merb-core/rack/adapter/thin.rb</filename>
    </modified>
    <modified>
      <diff>@@ -7,18 +7,11 @@ module Merb
     class ThinTurbo &lt; Thin
       # start a Thin Turbo server on given host and port.
 
-      # ==== Parameters
-      # opts&lt;Hash&gt;:: Options for Thin Turbo (see below).
-      #
-      # ==== Options (opts)
-      # :host&lt;String&gt;:: The hostname that Thin Turbo should serve.
-      # :port&lt;Fixnum&gt;:: The port Thin Turbo should bind to.
-      # :socket&lt;Fixnum&gt;&gt;:: The socket number that thin should bind to.
-      # :socket_file&lt;String&gt;&gt;:: The socket file that thin should attach to.
-      # :app&lt;String&gt;&gt;:: The application name.
-      def self.start(opts={})
-        super(opts.merge(:backend =&gt; ::Thin::Backends::Turbo))
+      def self.new_server(port)
+        @opts.merge!(:backend =&gt; ::Thin::Backends::Turbo)
+        super
       end
+
     end
   end
 end</diff>
      <filename>lib/merb-core/rack/adapter/thin_turbo.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,36 +1,72 @@
 require 'webrick'
+require 'webrick/utils'
 require 'rack/handler/webrick'
 module Merb
   module Rack
 
-    class WEBrick
-      # start WEBrick server on given host and port.
+    class WEBrick &lt; Merb::Rack::AbstractAdapter
       
-      # ==== Parameters
-      # opts&lt;Hash&gt;:: Options for WEBrick (see below).
-      #
-      # ==== Options (opts)
-      # :host&lt;String&gt;:: The hostname that WEBrick should serve.
-      # :port&lt;Fixnum&gt;:: The port WEBrick should bind to.
-      # :app&lt;String&gt;&gt;:: The application name.
-      def self.start(opts={})
-        Merb.logger.warn!(&quot;Using Webrick adapter&quot;)
+      class &lt;&lt; self
+        attr_accessor :server
+      end
       
+      def self.new_server(port)
         options = {
-          :Port        =&gt; opts[:port],
-          :BindAddress =&gt; opts[:host],
+          :Port        =&gt; port,
+          :BindAddress =&gt; @opts[:host],
           :Logger      =&gt; Merb.logger,
           :AccessLog   =&gt; [
             [Merb.logger, ::WEBrick::AccessLog::COMMON_LOG_FORMAT],
             [Merb.logger, ::WEBrick::AccessLog::REFERER_LOG_FORMAT]
           ]
         }
-     
-        server = ::WEBrick::HTTPServer.new(options)
-        Merb::Server.change_privilege
-        server.mount(&quot;/&quot;, ::Rack::Handler::WEBrick, opts[:app])
-        server.start
+
+        sockets = ::WEBrick::Utils.create_listeners nil, port
+        @server = ::WEBrick::HTTPServer.new(options.merge(:DoNotListen =&gt; true))
+        @server.listeners.replace sockets
       end
+      
+      def self.start_server
+        @server.mount(&quot;/&quot;, ::Rack::Handler::WEBrick, @opts[:app])
+        @server.start
+        exit(@status)
+      end
+      
+      def self.stop(status = 0)
+        @status = status
+        @server.shutdown
+      end
+      
+      def self.exit_process(status = 0)
+      end      
+      
+      # start WEBrick server on given host and port.
+      
+      # ==== Parameters
+      # opts&lt;Hash&gt;:: Options for WEBrick (see below).
+      #
+      # ==== Options (opts)
+      # :host&lt;String&gt;:: The hostname that WEBrick should serve.
+      # :port&lt;Fixnum&gt;:: The port WEBrick should bind to.
+      # :app&lt;String&gt;&gt;:: The application name.
+      # def self.start(opts={})
+      #   Merb.logger.warn!(&quot;Using Webrick adapter&quot;)
+      # 
+      #   options = {
+      #     :Port        =&gt; opts[:port],
+      #     :BindAddress =&gt; opts[:host],
+      #     :Logger      =&gt; Merb.logger,
+      #     :AccessLog   =&gt; [
+      #       [Merb.logger, ::WEBrick::AccessLog::COMMON_LOG_FORMAT],
+      #       [Merb.logger, ::WEBrick::AccessLog::REFERER_LOG_FORMAT]
+      #     ]
+      #   }
+      #      
+      #   server = ::WEBrick::HTTPServer.new(options)
+      #   Merb::Server.change_privilege
+      #   server.mount(&quot;/&quot;, ::Rack::Handler::WEBrick, opts[:app])
+      #   server.start
+      # end
     end
   end
 end
\ No newline at end of file</diff>
      <filename>lib/merb-core/rack/adapter/webrick.rb</filename>
    </modified>
    <modified>
      <diff>@@ -32,11 +32,15 @@ module Merb
         #   The hostname on which the app should run. Defaults to &quot;0.0.0.0&quot;
         # :Port&lt;Fixnum&gt;:: The port for the app. Defaults to 8080.
         def self.run(app, options={})
-          server = ::Mongrel::HttpServer.new(options[:Host] || '0.0.0.0',
+          @server = ::Mongrel::HttpServer.new(options[:Host] || '0.0.0.0',
                                              options[:Port] || 8080)
-          server.register('/', ::Merb::Rack::Handler::Mongrel.new(app))
-          yield server  if block_given?
-          server.run.join
+          @server.register('/', ::Merb::Rack::Handler::Mongrel.new(app))
+          yield @server  if block_given?
+          @server.run.join
+        end
+  
+        def self.stop(block = true)
+          @server.stop
         end
   
         # ==== Parameters</diff>
      <filename>lib/merb-core/rack/handler/mongrel.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,5 @@
 require 'etc'
+
 module Merb
 
   # Server encapsulates the management of Merb daemons.
@@ -18,46 +19,25 @@ module Merb
       # If cluster is left out, then one process will be started. This process
       # will be daemonized if Merb::Config[:daemonize] is true.
       def start(port, cluster=nil)
+        
         @port = port
-        @cluster = cluster
-        if @cluster
-          @port.to_i.upto(@port.to_i + @cluster.to_i-1) do |port|
-            pidfile = pid_file(port)
-            pid = IO.read(pidfile).chomp.to_i if File.exist?(pidfile)
+        @cluster = cluster        
 
-            unless alive?(port)
-              remove_pid_file(port)
-              puts &quot;Starting merb server on port #{port}, pid file: #{pidfile} and process id is #{pid}&quot; if Merb::Config[:verbose]
-              daemonize(port)
-            else
-              raise &quot;Merb is already running: port is #{port}, pid file: #{pidfile}, process id is #{pid}&quot;
-            end
-          end
-        elsif Merb::Config[:daemonize]
+        if Merb::Config[:daemonize]
           pidfile = pid_file(port)
-          pid = IO.read(pidfile).chomp.to_i if File.exist?(pidfile)
+          pid = File.read(pidfile).chomp.to_i if File.exist?(pidfile)
 
           unless alive?(@port)
             remove_pid_file(@port)
             puts &quot;Daemonizing...&quot; if Merb::Config[:verbose]
             daemonize(@port)
           else
-            raise &quot;Merb is already running: port is #{port}, pid file: #{pidfile}, process id is #{pid}&quot;
+            Merb.fatal! &quot;Merb is already running on port #{port}.\n&quot; \
+              &quot;\e[0m   \e[1;31;47mpid file: \e[34;47m#{pidfile}&quot; \
+              &quot;\e[1;31;47m, process id is \e[34;47m#{pid}.&quot;
           end
         else
-          trap('TERM') { exit }
-
-          if Merb::Config[:console_trap]
-            add_irb_trap
-          else
-            trap('INT') { puts &quot;\nExiting&quot;; exit }
-          end
-
-          puts &quot;Running bootloaders...&quot; if Merb::Config[:verbose]
-          BootLoader.run
-          puts &quot;Starting Rack adapter...&quot; if Merb::Config[:verbose]
-          Merb.logger.info! &quot;Starting Merb server listening at #{Merb::Config[:host]}:#{port}&quot;
-          Merb.adapter.start(Merb::Config.to_hash)
+          bootup
         end
       end
 
@@ -71,12 +51,14 @@ module Merb
         puts &quot;About to check if port #{port} is alive...&quot; if Merb::Config[:verbose]
         pidfile = pid_file(port)
         puts &quot;Pidfile is #{pidfile}...&quot; if Merb::Config[:verbose]
-        pid = IO.read(pidfile).chomp.to_i
+        pid = File.read(pidfile).chomp.to_i
         puts &quot;Process id is #{pid}&quot; if Merb::Config[:verbose]
         Process.kill(0, pid)
         true
-      rescue
+      rescue Errno::ESRCH, Errno::ENOENT
         false
+      rescue Errno::EACCES =&gt; e
+        Merb.fatal!(&quot;You don't have access to the PID file at #{pidfile}.&quot;, e)
       end
 
       # ==== Parameters
@@ -86,32 +68,49 @@ module Merb
       # ==== Alternatives
       # If you pass &quot;all&quot; as the port, the signal will be sent to all Merb
       # processes.
-      def kill(port, sig=9)
+      def kill(port, sig=&quot;INT&quot;)
         Merb::BootLoader::BuildFramework.run
         begin
-          pidfiles = port == &quot;all&quot; ?
-            pid_files : [ pid_file(port) ]
-
-          pidfiles.each do |f|
-            pid = IO.read(f).chomp.to_i
-            begin
-              Process.kill(sig, pid)
-              FileUtils.rm(f) if File.exist?(f)
-              puts &quot;killed PID #{pid} with signal #{sig}&quot;
-            rescue Errno::EINVAL
-              puts &quot;Failed to kill PID #{pid}: '#{sig}' is an invalid or unsupported signal number.&quot;
-            rescue Errno::EPERM
-              puts &quot;Failed to kill PID #{pid}: Insufficient permissions.&quot;
-            rescue Errno::ESRCH
-              puts &quot;Failed to kill PID #{pid}: Process is deceased or zombie.&quot;
-              FileUtils.rm f
-            rescue Exception =&gt; e
-              puts &quot;Failed to kill PID #{pid}: #{e.message}&quot;
+          if sig == 9 &amp;&amp; port == &quot;main&quot;
+            Dir[&quot;#{Merb.log_path}&quot; / &quot;*.pid&quot;].each do |file|
+              kill_pid(9, File.read(file).chomp.to_i, file)
             end
+          else
+            pid = File.read(pid_file(port)).chomp.to_i
+            kill_pid(sig, pid, pid_file(port))
+          end
+        rescue Errno::EACCES =&gt; e
+          Merb.fatal! e.message, e
+        rescue Errno::ENOENT =&gt; e
+          Merb.fatal! &quot;Could not find a PID file at #{pid_file(port)}&quot;, e           
+        end
+        if sig.is_a?(Integer)
+          sig = Signal.list.invert[sig]
+        end
+        if sig == &quot;KILL&quot; &amp;&amp; port == &quot;main&quot;
+          Merb.fatal! &quot;Killed all PIDs with signal KILL&quot;
+        else
+          Merb.fatal! &quot;Killed #{port} with signal #{sig}&quot;
+        end
+      end
+      
+      def kill_pid(sig, pid, file)
+        begin
+          Process.kill(sig, pid)
+          FileUtils.rm(file) if File.exist?(file)
+        rescue Errno::EINVAL
+          Merb.fatal! &quot;Failed to kill PID #{pid}: '#{sig}' is an invalid &quot; \
+            &quot;or unsupported signal number.&quot;
+        rescue Errno::EPERM
+          Merb.fatal! &quot;Failed to kill PID #{pid}: Insufficient permissions.&quot;
+        rescue Errno::ESRCH
+          FileUtils.rm file
+          Merb.fatal! &quot;Failed to kill PID #{pid}: Process is &quot; \
+            &quot;deceased or zombie.&quot;
+        rescue Exception =&gt; e
+          if !e.is_a?(SystemExit)
+            Merb.fatal! &quot;Failed to kill PID #{pid}&quot;, e
           end
-        ensure
-          Merb.started = false
-          exit
         end
       end
 
@@ -122,28 +121,45 @@ module Merb
         fork do
           Process.setsid
           exit if fork
+          Merb.logger.warn! &quot;In #{Process.pid}&quot; if Merb.logger
           File.umask 0000
           STDIN.reopen &quot;/dev/null&quot;
           STDOUT.reopen &quot;/dev/null&quot;, &quot;a&quot;
           STDERR.reopen STDOUT
-          trap(&quot;TERM&quot;) { exit }
-          Dir.chdir Merb::Config[:merb_root]
+          begin
+            Dir.chdir Merb::Config[:merb_root]
+          rescue Errno::EACCES =&gt; e
+            Merb.fatal! &quot;You specified #{Merb::Config[:merb_root]} &quot; \
+              &quot;as the Merb root, but you did not have access to it.&quot;, e
+          end
           at_exit { remove_pid_file(port) }
           Merb::Config[:port] = port
-          BootLoader.run
-          Merb.adapter.start(Merb::Config.to_hash)
+          bootup
         end
+      rescue NotImplementedError =&gt; e
+        Merb.fatal! &quot;Daemonized mode is not supported on your platform&quot;, e
+      end
+      
+      def bootup
+        trap('TERM') { exit }
+
+        puts &quot;Running bootloaders...&quot; if Merb::Config[:verbose]
+        BootLoader.run
+        puts &quot;Starting Rack adapter...&quot; if Merb::Config[:verbose]
+        Merb.adapter.start(Merb::Config.to_hash)
       end
 
       def change_privilege
-        if Merb::Config[:user]
-          if Merb::Config[:group]
-            puts &quot;About to change privilege to group #{Merb::Config[:group]} and user #{Merb::Config[:user]}&quot; if Merb::Config[:verbose]
-            _change_privilege(Merb::Config[:user], Merb::Config[:group])
-          else
-            puts &quot;About to change privilege to user #{Merb::Config[:user]}&quot; if Merb::Config[:verbose]
-            _change_privilege(Merb::Config[:user])
-          end
+        if Merb::Config[:user] &amp;&amp; Merb::Config[:group]
+          Merb.logger.verbose! &quot;About to change privilege to group &quot; \
+            &quot;#{Merb::Config[:group]} and user #{Merb::Config[:user]}&quot;
+          _change_privilege(Merb::Config[:user], Merb::Config[:group])
+        elsif Merb::Config[:user]
+          Merb.logger.verbose! &quot;About to change privilege to user &quot; \
+            &quot;#{Merb::Config[:user]}&quot;
+          _change_privilege(Merb::Config[:user])
+        else
+          return true
         end
       end
 
@@ -160,8 +176,10 @@ module Merb
       # instead of the port based PID file.
       def remove_pid_file(port)
         pidfile = pid_file(port)
-        puts &quot;Removing pid file #{pidfile} (port is #{port})...&quot;
-        FileUtils.rm(pidfile) if File.exist?(pidfile)
+        if File.exist?(pidfile)
+          puts &quot;Removing pid file #{pidfile} (port is #{port})...&quot;
+          FileUtils.rm(pidfile)
+        end
       end
 
       # Stores a PID file on the filesystem.
@@ -176,11 +194,23 @@ module Merb
       # If Merb::Config[:pid_file] has been specified, that will be used
       # instead of the port based PID file.
       def store_pid(port)
-        pidfile = pid_file(port)
-        puts &quot;Storing pid file to #{pidfile}...&quot;
-        FileUtils.mkdir_p(File.dirname(pidfile)) unless File.directory?(File.dirname(pidfile))
-        puts &quot;Created directory, writing process id...&quot; if Merb::Config[:verbose]
-        File.open(pidfile, 'w'){ |f| f.write(&quot;#{Process.pid}&quot;) }
+        store_details(port)
+      end
+
+      def remove_pid(port)
+        FileUtils.rm(pid_file(port)) if File.file?(pid_file(port))
+      end
+
+      def store_details(port = nil)
+        file = pid_file(port)
+        begin
+          FileUtils.mkdir_p(File.dirname(file))
+        rescue Errno::EACCES =&gt; e
+          Merb.fatal! &quot;You tried to store Merb logs in #{File.dirname(file)}, &quot; \
+            &quot;but you did not have access.&quot;, e
+        end
+        Merb.logger.warn! &quot;Storing #{type} file to #{file}...&quot; if Merb::Config[:verbose]
+        File.open(file, 'w'){ |f| f.write(Process.pid.to_s) }
       end
 
       # Gets the pid file for the specified port.
@@ -194,20 +224,8 @@ module Merb
       #   Location of pid file for specified port. If clustered and pid_file option
       #   is specified, it adds the port value to the path.
       def pid_file(port)
-        if Merb::Config[:pid_file]
-          pidfile = Merb::Config[:pid_file]
-          if Merb::Config[:cluster]
-            ext = File.extname(Merb::Config[:pid_file])
-            base = File.basename(Merb::Config[:pid_file], ext)
-            dir = File.dirname(Merb::Config[:pid_file])
-            File.join(dir, &quot;#{base}.#{port}#{ext}&quot;)
-          else
-            Merb::Config[:pid_file]
-          end
-        else
-          pidfile = Merb.log_path / &quot;merb.#{port}.pid&quot;
-          Merb.log_path / &quot;merb.#{port}.pid&quot;
-        end
+        pidfile = Merb::Config[:pid_file] || (Merb.log_path / &quot;merb.%s.pid&quot;)
+        pidfile % port
       end
 
       # Get a list of the pid files.
@@ -218,10 +236,7 @@ module Merb
       def pid_files
         if Merb::Config[:pid_file]
           if Merb::Config[:cluster]
-            ext = File.extname(Merb::Config[:pid_file])
-            base = File.basename(Merb::Config[:pid_file], ext)
-            dir = File.dirname(Merb::Config[:pid_file])
-            Dir[dir / &quot;#{base}.*#{ext}&quot;]
+            Dir[Merb::Config[:pid_file] % &quot;*&quot;]
           else
             [ Merb::Config[:pid_file] ]
           end
@@ -240,11 +255,25 @@ module Merb
       # If group is left out, the user will be used as the group.
       def _change_privilege(user, group=user)
 
-        puts &quot;Changing privileges to #{user}:#{group}&quot;
+        Merb.logger.warn! &quot;Changing privileges to #{user}:#{group}&quot;
 
         uid, gid = Process.euid, Process.egid
-        target_uid = Etc.getpwnam(user).uid
-        target_gid = Etc.getgrnam(group).gid
+        
+        begin
+          target_uid = Etc.getpwnam(user).uid
+        rescue ArgumentError =&gt; e
+          Merb.fatal!(
+            &quot;You tried to use user #{user}, but no such user was found&quot;, e)
+          return false
+        end
+        
+        begin
+          target_gid = Etc.getgrnam(group).gid
+        rescue ArgumentError =&gt; e
+          Merb.fatal!(
+            &quot;You tried to use group #{group}, but no such group was found&quot;, e)
+          return false
+        end
 
         if uid != target_uid || gid != target_gid
           # Change process ownership
@@ -252,13 +281,19 @@ module Merb
           Process::GID.change_privilege(target_gid)
           Process::UID.change_privilege(target_uid)
         end
+        true
       rescue Errno::EPERM =&gt; e
-        puts &quot;Couldn't change user and group to #{user}:#{group}: #{e}&quot;
+        Merb.fatal! &quot;Couldn't change user and group to #{user}:#{group}&quot;, e
+        false
       end
 
       def add_irb_trap
         trap('INT') do
-          exit if @interrupted
+          if @interrupted
+            puts &quot;Exiting\n&quot;
+            exit
+          end
+          
           @interrupted = true
           puts &quot;Interrupt a second time to quit&quot;
           Kernel.sleep 1.5</diff>
      <filename>lib/merb-core/server.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,6 @@
 module Merb::Test::MultipartRequestHelper
   require 'rubygems'
+  gem &quot;mime-types&quot;
   require 'mime/types'
 
   class Param</diff>
      <filename>lib/merb-core/test/helpers/multipart_request_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -56,12 +56,12 @@ describe Merb::Config do
 
   it &quot;should support -c to set the number of cluster nodes&quot; do
     Merb::Config.parse_args([&quot;-c&quot;, &quot;4&quot;])
-    Merb::Config[:cluster].should == &quot;4&quot;
+    Merb::Config[:cluster].should == 4
   end
 
   it &quot;should support -p to set the port number&quot; do
     Merb::Config.parse_args([&quot;-p&quot;, &quot;6000&quot;])
-    Merb::Config[:port].should == &quot;6000&quot;
+    Merb::Config[:port].should == 6000
   end
 
   it &quot;should support -o to set the socket filename&quot; do
@@ -76,12 +76,12 @@ describe Merb::Config do
 
   it &quot;should support -s to set the socket number&quot; do
     Merb::Config.parse_args([&quot;-s&quot;, &quot;0&quot;])
-    Merb::Config[:socket].should == &quot;0&quot;
+    Merb::Config[:socket].should == 0
   end
 
   it &quot;should support --socket to set the socket number&quot; do
     Merb::Config.parse_args([&quot;--socket&quot;, &quot;3&quot;])
-    Merb::Config[:socket].should == &quot;3&quot;
+    Merb::Config[:socket].should == 3
   end
 
   it &quot;should support -P to set the PIDfile&quot; do
@@ -96,7 +96,7 @@ describe Merb::Config do
   end
 
   it &quot;should support setting of PIDfile with cluster nodes&quot; do
-    Merb::Config.parse_args([&quot;-P&quot;, &quot;/tmp/merb.pidfile&quot;, &quot;-c&quot;, &quot;2&quot;, &quot;-p&quot;, &quot;6000&quot;])
+    Merb::Config.parse_args([&quot;-P&quot;, &quot;/tmp/merb.%s.pidfile&quot;, &quot;-c&quot;, &quot;2&quot;, &quot;-p&quot;, &quot;6000&quot;])
     Merb::Server.pid_file(6000).should == &quot;/tmp/merb.6000.pidfile&quot;
     Merb::Server.pid_file(6001).should == &quot;/tmp/merb.6001.pidfile&quot;
 
@@ -144,12 +144,12 @@ describe Merb::Config do
   end
 
   it &quot;should support -K for a graceful kill&quot; do
-    Merb::Server.should_receive(:kill).with(&quot;all&quot;, 1)
+    Merb::Server.should_receive(:kill).with(&quot;main&quot;, 2)
     Merb.start([&quot;-K&quot;, &quot;all&quot;])
   end
 
   it &quot;should support -k for a hard kill&quot; do
-    Merb::Server.should_receive(:kill).with(&quot;all&quot;, 9)
+    Merb::Server.should_receive(:kill).with(&quot;main&quot;, 9)
     Merb.start([&quot;-k&quot;, &quot;all&quot;])
   end
 </diff>
      <filename>spec/private/config/config_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -31,149 +31,164 @@ describe Merb::Logger do
   describe &quot;#set_log&quot; do
 
     before(:each) do
-      @logger = Merb::Logger.new(Merb.log_file)
+      # @logger = Merb::Logger.new(Merb.log_file)
     end
 
     it &quot;should set the log level to :warn (4) when second parameter is :warn&quot; do
-      Merb::Logger.new(Merb.log_file, :warn).level.should eql(4)
+      Merb::Config[:log_level] = :warn
+      Merb.logger = nil
+      Merb.logger.level.should == 4
     end
 
     it &quot;should set the log level to :debug (0) when Merb.environment is development&quot; do
-      Merb.should_receive(:environment).and_return(&quot;development&quot;)
-      @logger.set_log(Merb.log_path / &quot;development.log&quot;)
-      @logger.level.should eql(0)
+      Merb.environment = &quot;development&quot;
+      Merb::Config.delete(:log_level)
+      Merb.logger = nil
+      Merb::BootLoader::Logger.run
+      Merb.logger.level.should == 0
     end
     
     it &quot;should set the log level to :error (6) when Merb.environment is production&quot; do
-      Merb.should_receive(:environment).and_return(&quot;production&quot;)
-      @logger.set_log(Merb.log_path / &quot;production.log&quot;)
-      @logger.level.should eql(4)
+      Merb.environment = &quot;production&quot;
+      Merb::Config.delete(:log_level)
+      Merb.logger = nil
+      Merb::BootLoader::Logger.run
+      Merb.logger.level.should == 4
     end
     
-    it &quot;should initialize the buffer to an empty array&quot; do
-      @logger.buffer.should eql([])
-    end
-
     it &quot;should default the delimiter to ' ~ '&quot; do
-      @logger.delimiter.should eql(&quot; ~ &quot;)
-    end
-    
-    it &quot;should assign the newly created object to Merb.logger&quot; do
-      @logger = Merb::Logger.new(Merb.log_file)
-      Merb.logger.should eql(@logger)
-    end
+      Merb.logger.delimiter.should eql(&quot; ~ &quot;)
+    end    
     
   end
   
   describe &quot;#flush&quot; do
 
-    before(:each) do
-      @logger = Merb::Logger.new(Merb.log_file)
-    end
-    
     it &quot;should immediately return if the buffer is empty&quot; do
-      @logger.should_not_receive(:write)
-      @logger.flush
+      Merb::Config[:log_stream] = StringIO.new
+      Merb.logger = nil
+      
+      Merb.logger.flush
+      Merb::Config[:log_stream].string.should == &quot;&quot;
     end
 
     it &quot;should call the write_method with the stringified contents of the buffer if the buffer is non-empty&quot; do
-      @logger.send(:&lt;&lt;, &quot;a message&quot;)
-      @logger.send(:&lt;&lt;, &quot;another message&quot;)
-      @logger.log.should_receive(:write).with(&quot; ~ a message\n ~ another message\n&quot;)
-      @logger.flush
+      Merb::Config[:log_stream] = StringIO.new
+      Merb.logger = nil
+      
+      Merb.logger &lt;&lt; &quot;a message&quot;
+      Merb.logger &lt;&lt; &quot;another message&quot;
+      Merb.logger.flush
+      
+      Merb::Config[:log_stream].string.should == &quot; ~ a message\n ~ another message\n&quot;
     end
 
   end
   
-  describe &quot;#close&quot; do
-    before(:each) do
-      @logger = Merb::Logger.new(Merb.log_file)
-    end
+  # There were close specs here, but the logger isn't an IO anymore, and
+  # shares a stream with other loggers, so it shouldn't be closing the
+  # stream.
 
-    it &quot;should flush the buffer before closing&quot; do
-      # TODO: how to specify order? eg. flush then close
-      @logger.should_receive(:flush)
-      @logger.log.should_receive(:close)
-      @logger.close
-    end
+  describe &quot;level methods&quot; do
 
-    it &quot;should call the close method if the log responds to close&quot; do
-      @logger.log.should_receive(:close)
-      @logger.close
+    def set_level(level)
+      Merb::Config[:log_level] = level
+      Merb.logger = nil
     end
 
-    it &quot;shouldn't call the close method if the log is a terminal&quot; do
-      @logger.log.should_receive(:tty?).and_return(true)
-      @logger.log.should_not_receive(:close)
-      @logger.close
+    before(:each) do
+      @stream = Merb::Config[:log_stream] = StringIO.new
     end
 
-    it &quot;should set the stored log attribute to nil&quot; do
-      @logger.close
-      @logger.log.should eql(nil)
+    it &quot;should provide a #debug method which adds to the buffer in level :debug&quot; do
+      set_level(:debug)
+      Merb.logger.debug(&quot;message&quot;)
+      Merb.logger.flush
+      @stream.string.should == &quot; ~ message\n&quot;
     end
 
-  end
-
-  describe &quot;&lt;&lt;&quot; do
+    it &quot;should provide a #debug method which does not add to the buffer &quot; \
+      &quot;in level :info or higher&quot; do
+      set_level(:info)
+      Merb.logger.debug(&quot;message&quot;)
+      Merb.logger.flush
+      @stream.string.should == &quot;&quot;
+    end
     
-  end
-
-  describe &quot;level methods&quot; do
+    it &quot;should provide an #info method which adds to the buffer in &quot; \
+      &quot;level :info or below&quot; do
+      set_level(:info)
+      Merb.logger.info(&quot;message&quot;)
+      Merb.logger.flush
+      @stream.string.should == &quot; ~ message\n&quot;
+    end
 
-    before(:all) do
-      @logger = Merb::Logger.new(Merb.log_file)
+    it &quot;should provide a #info method which does not add to the buffer &quot; \
+      &quot;in level :warn or higher&quot; do
+      set_level(:warn)
+      Merb.logger.info(&quot;message&quot;)
+      Merb.logger.flush
+      @stream.string.should == &quot;&quot;
     end
 
-    it &quot;should provide a #debug method which can be used to log&quot; do
-      @logger.should respond_to(:debug)
-      @logger.should_receive(:&lt;&lt;).with(&quot;message&quot;).and_return(true)
-      @logger.debug(&quot;message&quot;)
+    it &quot;should provide a #warn method which adds to the buffer in &quot; \
+      &quot;level :warn or below&quot; do
+      set_level(:warn)
+      Merb.logger.warn(&quot;message&quot;)
+      Merb.logger.flush
+      @stream.string.should == &quot; ~ message\n&quot;
     end
 
-    it &quot;should provide a #info method which can be used to log&quot; do
-      @logger.should respond_to(:info)
-      @logger.should_receive(:&lt;&lt;).with(&quot;message&quot;).and_return(true)
-      @logger.info(&quot;message&quot;)
+    it &quot;should provide a #warn method which does not add to the buffer &quot; \
+      &quot;in level :error or higher&quot; do
+      set_level(:error)
+      Merb.logger.warn(&quot;message&quot;)
+      Merb.logger.flush
+      @stream.string.should == &quot;&quot;
     end
 
-    it &quot;should provide a #warn method which can be used to log&quot; do
-      @logger.should respond_to(:warn)
-      @logger.should_receive(:&lt;&lt;).with(&quot;message&quot;).and_return(true)
-      @logger.warn(&quot;message&quot;)
+    it &quot;should provide a #error method which adds to the buffer in &quot; \
+      &quot;level :error or below&quot; do
+      set_level(:error)
+      Merb.logger.error(&quot;message&quot;)
+      Merb.logger.flush
+      @stream.string.should == &quot; ~ message\n&quot;
     end
 
-    it &quot;should provide a #error method which can be used to log&quot; do
-      @logger.should respond_to(:error)
-      @logger.should_receive(:&lt;&lt;).with(&quot;message&quot;).and_return(true)
-      @logger.error(&quot;message&quot;)
+    it &quot;should provide a #error method which does not add to the buffer &quot; \
+      &quot;in level :fatal or higher&quot; do
+      set_level(:fatal)
+      Merb.logger.error(&quot;message&quot;)
+      Merb.logger.flush
+      @stream.string.should == &quot;&quot;
     end
 
-    it &quot;should provide a #fatal method which can be used to log&quot; do
-      @logger.should respond_to(:fatal)
-      @logger.should_receive(:&lt;&lt;).with(&quot;message&quot;).and_return(true)
-      @logger.fatal(&quot;message&quot;)
+    it &quot;should provide a #fatal method which always logs&quot; do
+      set_level(:fatal)
+      Merb.logger.fatal(&quot;message&quot;)
+      Merb.logger.flush
+      @stream.string.should == &quot; ~ message\n&quot;
     end
     
     # TODO: add positive and negative tests for each of the methods below:
     it &quot;should provide a #debug? method&quot; do
-      @logger.should respond_to(:debug?)
+      Merb.logger.should respond_to(:debug?)
     end
 
     it &quot;should provide a #info? method&quot; do
-      @logger.should respond_to(:info?)
+      Merb.logger.should respond_to(:info?)
     end
 
     it &quot;should provide a #warn? method&quot; do
-      @logger.should respond_to(:warn?)
+      Merb.logger.should respond_to(:warn?)
     end
 
     it &quot;should provide a #error? method&quot; do
-      @logger.should respond_to(:error?)
+      Merb.logger.should respond_to(:error?)
     end
 
     it &quot;should provide a #fatal? method&quot; do
-      @logger.should respond_to(:fatal?)
+      Merb.logger.should respond_to(:fatal?)
     end
 
   end</diff>
      <filename>spec/public/logger/logger_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,103 +1,103 @@
-require File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;..&quot;, &quot;spec_helper&quot;)
-
-class MockTimedExecutor
-  def self.every(seconds, &amp;block)
-    @@scheduled_action = block
-  end
-  def self.run_task
-    @@scheduled_action.call 
-  end
-end
-
-RealTimedExecutor = Merb::BootLoader::ReloadClasses::TimedExecutor
-Merb::BootLoader::ReloadClasses::TimedExecutor = MockTimedExecutor
-
-Merb.start :environment =&gt; 'test',
-           :merb_root =&gt; File.dirname(__FILE__) / &quot;directory&quot;
-
-describe &quot;TimedExecutor&quot; do
-  it &quot;should call a block of code repeatedly in the background&quot; do
-    list_of_things = []
-    
-    RealTimedExecutor.every(0.1) do
-      list_of_things &lt;&lt; &quot;Something&quot;
-    end
-    
-    sleep 0.5
-    
-    list_of_things.should_not be_empty
-    list_of_things.size.should &gt; 1
-  end
-  
-end
-
-describe &quot;The reloader&quot; do
-
-  before :all do
-    @reload_file = File.dirname(__FILE__) / &quot;directory&quot; / &quot;app&quot; / &quot;controllers&quot; / &quot;reload.rb&quot;
-    @text =  &lt;&lt;-END
-
-        class Reloader &lt; Application
-        end
-
-        class Hello &lt; Application
-        end
-      END
-     update_file @text
-     MockTimedExecutor.run_task
-  end
-
-  def update_file(contents)
-    mtime = File.mtime(@reload_file)
-    f = File.open(@reload_file, &quot;w&quot;) do |f|
-      f.puts contents
-    end
-    File.utime(mtime+30, mtime+30, @reload_file)
-  end
-
-  it &quot;should reload files that were changed&quot; do
-    defined?(Hello).should_not be_nil
-    defined?(Reloader).should_not be_nil
-    defined?(Reloader2).should be_nil
-
-    update_file &lt;&lt;-END
-
-        class Reloader &lt; Application
-        end
-
-        class Reloader2
-        end
-      END
-     
-    MockTimedExecutor.run_task
-    
-    defined?(Hello).should be_nil
-    defined?(Reloader).should_not be_nil
-    defined?(Reloader2).should_not be_nil
-  end
-
-  it &quot;should remove classes for _abstract_subclasses&quot; do
-    
-    update_file &lt;&lt;-END
-
-        class Reloader &lt; Application
-        end
-
-        class Reloader2 &lt; Application
-        end
-      END
-    
-    MockTimedExecutor.run_task
-
-    Merb::AbstractController._abstract_subclasses.should include(&quot;Reloader&quot;)
-    Merb::AbstractController._abstract_subclasses.should include(&quot;Reloader2&quot;)
-    defined?(Hello).should be_nil
-    defined?(Reloader).should_not be_nil
-    defined?(Reloader2).should_not be_nil
-  end
-
-  after :each do
-    update_file @text
-    MockTimedExecutor.run_task
-  end
-end
+# require File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;..&quot;, &quot;spec_helper&quot;)
+# 
+# class MockTimedExecutor
+#   def self.every(seconds, &amp;block)
+#     @@scheduled_action = block
+#   end
+#   def self.run_task
+#     @@scheduled_action.call 
+#   end
+# end
+# 
+# RealTimedExecutor = Merb::BootLoader::ReloadClasses::TimedExecutor
+# Merb::BootLoader::ReloadClasses::TimedExecutor = MockTimedExecutor
+# 
+# Merb.start :environment =&gt; 'test',
+#            :merb_root =&gt; File.dirname(__FILE__) / &quot;directory&quot;
+# 
+# describe &quot;TimedExecutor&quot; do
+#   it &quot;should call a block of code repeatedly in the background&quot; do
+#     list_of_things = []
+#     
+#     RealTimedExecutor.every(0.1) do
+#       list_of_things &lt;&lt; &quot;Something&quot;
+#     end
+#     
+#     sleep 0.5
+#     
+#     list_of_things.should_not be_empty
+#     list_of_things.size.should &gt; 1
+#   end
+#   
+# end
+# 
+# describe &quot;The reloader&quot; do
+# 
+#   before :all do
+#     @reload_file = File.dirname(__FILE__) / &quot;directory&quot; / &quot;app&quot; / &quot;controllers&quot; / &quot;reload.rb&quot;
+#     @text =  &lt;&lt;-END
+# 
+#         class Reloader &lt; Application
+#         end
+# 
+#         class Hello &lt; Application
+#         end
+#       END
+#      update_file @text
+#      MockTimedExecutor.run_task
+#   end
+# 
+#   def update_file(contents)
+#     mtime = File.mtime(@reload_file)
+#     f = File.open(@reload_file, &quot;w&quot;) do |f|
+#       f.puts contents
+#     end
+#     File.utime(mtime+30, mtime+30, @reload_file)
+#   end
+# 
+#   it &quot;should reload files that were changed&quot; do
+#     defined?(Hello).should_not be_nil
+#     defined?(Reloader).should_not be_nil
+#     defined?(Reloader2).should be_nil
+# 
+#     update_file &lt;&lt;-END
+# 
+#         class Reloader &lt; Application
+#         end
+# 
+#         class Reloader2
+#         end
+#       END
+#      
+#     MockTimedExecutor.run_task
+#     
+#     defined?(Hello).should be_nil
+#     defined?(Reloader).should_not be_nil
+#     defined?(Reloader2).should_not be_nil
+#   end
+# 
+#   it &quot;should remove classes for _abstract_subclasses&quot; do
+#     
+#     update_file &lt;&lt;-END
+# 
+#         class Reloader &lt; Application
+#         end
+# 
+#         class Reloader2 &lt; Application
+#         end
+#       END
+#     
+#     MockTimedExecutor.run_task
+# 
+#     Merb::AbstractController._abstract_subclasses.should include(&quot;Reloader&quot;)
+#     Merb::AbstractController._abstract_subclasses.should include(&quot;Reloader2&quot;)
+#     defined?(Hello).should be_nil
+#     defined?(Reloader).should_not be_nil
+#     defined?(Reloader2).should_not be_nil
+#   end
+# 
+#   after :each do
+#     update_file @text
+#     MockTimedExecutor.run_task
+#   end
+# end</diff>
      <filename>spec/public/reloading/reload_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -28,8 +28,8 @@ module Merb
         end
         
         def matches?(target)
-          target.log.rewind
-          @text = target.log.read
+          target.rewind
+          @text = target.read
           @text =~ (String === @expected ? /#{Regexp.escape @expected}/ : @expected)
         end
         
@@ -108,9 +108,11 @@ Spec::Runner.configure do |config|
   end
 
   def with_level(level)
-    Merb.logger = Merb::Logger.new(StringIO.new, level)
+    Merb::Config[:log_stream] = StringIO.new
+    Merb::Config[:log_level] = level
+    Merb.logger = nil
     yield
-    Merb.logger
+    Merb::Config[:log_stream]
   end
 
   def capture(stream)</diff>
      <filename>spec/spec_helper.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>0f4957f2e03ba79eb914563507b0582738fb5d37</id>
    </parent>
  </parents>
  <author>
    <name>Michael S. Klishin</name>
    <email>michael@novemberain.com</email>
  </author>
  <url>http://github.com/wycats/merb-core/commit/a6f6a986ab3aa1414368d24892a808c448ecb564</url>
  <id>a6f6a986ab3aa1414368d24892a808c448ecb564</id>
  <committed-date>2008-09-27T23:06:08-07:00</committed-date>
  <authored-date>2008-09-27T23:06:08-07:00</authored-date>
  <message>Merge in forking branch.

* Merb starts with master and worker processes now.
* Logger is now 100% thread safe and works on current JRuby.
* New options for fast redeploy/restart of cluster.
* Reloading machinery should be bullet proof now.

Squashed commit of the following:

commit 4405ac5db172a40d533b71a0a57a3233aea13435
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Sun Sep 28 01:24:39 2008 -0400

    Add --fast-deploy option

commit 247779ebe96100b49690581801a897636e72b36a
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Sun Sep 28 01:19:39 2008 -0400

    Operator precedence ftl

commit 55dcdc6fbc29257dcaf25997d59cdf66fb66a507
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Sun Sep 28 00:31:53 2008 -0400

    Somehow the code that supports a single log file went missing :P

commit afc291cd9d5c660c4071741b21e79a3df62223f2
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Sat Sep 27 16:23:28 2008 -0400

    Tests pass: we don't need to fork for class load in test env, plus update config spec for some small changes to the internal API

commit 67e1756c267edb27f0229e0e7f9883736868742a
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Sat Sep 27 16:14:16 2008 -0400

    get merb -k and merb -K to work (with and without `all')

commit eb52fcec508a458af4d2d286223960b24a2954c3
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Sat Sep 27 16:13:48 2008 -0400

    Fix bug with creating a new log

commit 70a47b4b70c67a0328f1845fab0f9ef258a1ec87
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Fri Sep 26 23:58:28 2008 -0700

    Reload spec needs to be added back later; logger specs work again after removing mocks and modifying specs for public API changes

commit fdc4ec0c04073e4ffca7d484152dbaedf02f1f97
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Fri Sep 26 23:38:57 2008 -0700

    Fix logger helper

commit d22b8e6c60b48718e7484a1154a2211c5fa17404
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Fri Sep 26 22:12:14 2008 -0700

    Attempt threadsafe logger

commit 205f2436a741841abc92901c015f3c470a5b99b7
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Thu Sep 25 23:57:07 2008 -0700

    Hide the backtrace for Mongrel timeout errors.

commit 27779e1f857c3555c87451a1011bbeee646fa1f5
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Thu Sep 25 23:22:17 2008 -0700

    Respawn processes killed with kill -9

commit f4fd0d39ea76e1722ee115f15f307732603d7ce4
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Thu Sep 25 23:18:02 2008 -0700

    Tons of comments; support for various forking configurations

commit acb90a6e57e075717a235f5896df545937880416
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Thu Sep 25 22:32:13 2008 -0700

    Forking setup works without any forking.

commit ab4f142a2433452c940696d2f6bd9e23e375ea20
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Thu Sep 25 17:59:58 2008 -0700

    Update thin for new stop() API

commit e5937d5a6a08d29fcf0d40b3eb6e18a6dc7191a7
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Thu Sep 25 17:58:35 2008 -0700

    Added better errors for failures originating with Merb

commit 04e2a9b4e7e997613d0f712d4d79612304066808
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Thu Sep 25 17:57:20 2008 -0700

    Checked in experiments (for posterity)

commit 7e8385254168c99e39208fbadbdb4758c9f52b92
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Thu Sep 25 13:16:56 2008 -0700

    All Ruby-based servers work now with forking; NEXT: Make forking only happen when appropriate

commit abe9f500695154adc0da4535652ef8a070435875
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Thu Sep 25 01:35:33 2008 -0700

    Help REE make better use of GC

commit 388941a35c0454153f0e80ae9ec9deb44c5d2252
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Wed Sep 24 23:47:13 2008 -0700

    Ebb works

commit a5b48f4ba2ac499a020d748466f8cba2a8223fb6
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Wed Sep 24 22:26:07 2008 -0700

    Someone should figure out why I had to make the change I needed to in config.rb; abstract up the API for making a new forkable process; thin-turbo appears to have some issues

commit 6e2a107c4bec7281ff944b92dd426f1c47137663
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Wed Sep 24 12:10:55 2008 -0700

    Fix some more issues relating to graceful exits; remove pids on exit; TODO: merb -k must work

commit 717d5a8667a1fc206061c007e00528643676fb5e
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Wed Sep 24 00:05:26 2008 -0700

    Tighten things up so that ctrl-c works correctly

commit 76eba224d0beed7a32a2e20826f0f0574a4e20c9
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Tue Sep 23 21:18:20 2008 -0700

    Reload works again

commit ca5d6b2a3df884a074d289a41eeb56f540849686
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Tue Sep 23 18:32:55 2008 -0700

    Finish up making mongrel handle everything correctly. We need to update merb -k to use the new signals.

commit 9ec4de2155eab3f398138889584f3dfd25d226c2
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Tue Sep 23 10:16:04 2008 -0700

    More forking support

commit ec7cfae89c157333a3df6c57a9b1987caf51f7e4
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Sat Sep 20 00:52:47 2008 -0500

    Initial experiments are a success. TODO: Move the logic out of mongrel and make a proper clustering instead of hardcoding to 4

commit aceea3838234535573aa02c2d914d65c11a1ceb5
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Fri Sep 19 18:47:09 2008 -0500

    Split out the code transaction into a method and do some experimentation with cluster forking.

commit 56e09f16c302126864c72adf9ecbdf992b29c8a3
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Fri Sep 19 13:43:39 2008 -0700

    Better exit message

commit 2b67c34ac05de5c48260baa9a6f0d95f70101ab4
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Fri Sep 19 13:10:19 2008 -0700

    Initial support for fast redeploys and code reloading via forks.

commit b7e9fc3e9f08c7970d1b6d69928e832511c7f2fe
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Fri Sep 26 23:58:28 2008 -0700

    Reload spec needs to be added back later; logger specs work again after removing mocks and modifying specs for public API changes

commit bdf5c2d82d7420f4604e48f60e69e2d2f037858a
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Fri Sep 26 23:38:57 2008 -0700

    Fix logger helper

commit 8b09d459156158673d174a2d86cc32bf5175049c
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Fri Sep 26 22:12:14 2008 -0700

    Attempt threadsafe logger

commit b3b0eb25e3037031a34588683be8e6d6c8db621c
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Thu Sep 25 23:57:07 2008 -0700

    Hide the backtrace for Mongrel timeout errors.

commit 315d89c21f13b32c6db4d58ce945be361061ca6f
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Thu Sep 25 23:22:17 2008 -0700

    Respawn processes killed with kill -9

commit a7ba4dbb14aa0a3e6a56757713f18820b241c982
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Thu Sep 25 23:18:02 2008 -0700

    Tons of comments; support for various forking configurations

commit 093d38fcb65f67ac44e786e266475c88f7c16d38
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Thu Sep 25 22:32:13 2008 -0700

    Forking setup works without any forking.

commit 9e4d8c861806c782b99b00bcbc98ee1223113fc7
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Thu Sep 25 17:59:58 2008 -0700

    Update thin for new stop() API

commit 7c376ee3dd3e797026b5e0917a58c897d8a623f5
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Thu Sep 25 17:58:35 2008 -0700

    Added better errors for failures originating with Merb

commit 0ea49649648e307f7289edee928a8485ba96f75f
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Thu Sep 25 17:57:20 2008 -0700

    Checked in experiments (for posterity)

commit da7611a85255b5fb80e728bb7af48dfba8ff44d0
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Thu Sep 25 13:16:56 2008 -0700

    All Ruby-based servers work now with forking; NEXT: Make forking only happen when appropriate

commit 5cd1901d7edd8cc98a2b83da45b4a85ff741f0e8
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Thu Sep 25 01:35:33 2008 -0700

    Help REE make better use of GC

commit 291c3127375786fd64d0808327670d702157f30c
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Wed Sep 24 23:47:13 2008 -0700

    Ebb works

commit 956782efc0ab3877eb0161c0b9140fb118db4d4d
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Wed Sep 24 22:26:07 2008 -0700

    Someone should figure out why I had to make the change I needed to in config.rb; abstract up the API for making a new forkable process; thin-turbo appears to have some issues

commit 099dc18ff81094a707790e99a922504e661aeba0
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Wed Sep 24 12:10:55 2008 -0700

    Fix some more issues relating to graceful exits; remove pids on exit; TODO: merb -k must work

commit d209193a88ab5d522213e4f1747942e1b04b21f3
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Wed Sep 24 00:05:26 2008 -0700

    Tighten things up so that ctrl-c works correctly

commit bd10fe6dfcd197b602474f9afd6075db337fb005
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Tue Sep 23 21:18:20 2008 -0700

    Reload works again

commit 6c2ebcc54a48ac0ef678ac544ebe22858ed5029c
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Tue Sep 23 18:32:55 2008 -0700

    Finish up making mongrel handle everything correctly. We need to update merb -k to use the new signals.

commit 412c4c163dfa363a7c64e047ec4e54c1b61832a4
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Tue Sep 23 10:16:04 2008 -0700

    More forking support

commit 94c5eb8d213b107b1c82314cb972649226629376
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Sat Sep 20 00:52:47 2008 -0500

    Initial experiments are a success. TODO: Move the logic out of mongrel and make a proper clustering instead of hardcoding to 4

commit 9a57de6ab3253280b90e3e4bf9dc49b1b2a51c61
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Fri Sep 19 18:47:09 2008 -0500

    Split out the code transaction into a method and do some experimentation with cluster forking.

commit 71306ed36084efcafcb51f07bb426509f9fafe4a
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Fri Sep 19 13:43:39 2008 -0700

    Better exit message

commit b7dac300dc08fc8d89e1e2344c4ec77a5e0ad5b6
Author: Yehuda Katz &lt;wycats@gmail.com&gt;
Date:   Fri Sep 19 13:10:19 2008 -0700

    Initial support for fast redeploys and code reloading via forks.</message>
  <tree>bd147d0913731b6aaffcc209d49c8d1c3d6fd355</tree>
  <committer>
    <name>Michael S. Klishin</name>
    <email>michael@novemberain.com</email>
  </committer>
</commit>
