<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -566,7 +566,7 @@ class Merb::BootLoader::LoadClasses &lt; Merb::BootLoader
 
       # Log the process configuration user defined signal 1 (SIGUSR1) is received.
       Merb.trap(&quot;USR1&quot;) do
-        Merb.logger.error! &quot;Configuration:\n#{Merb::Config.to_hash.merge(:pid =&gt; $$).to_yaml}\n\n&quot;
+        Merb.logger.fatal! &quot;Configuration:\n#{Merb::Config.to_hash.merge(:pid =&gt; $$).to_yaml}\n\n&quot;
       end
 
       if Merb::Config[:fork_for_class_load] &amp;&amp; !Merb.testing?
@@ -600,8 +600,11 @@ class Merb::BootLoader::LoadClasses &lt; Merb::BootLoader
     #
     # @api private
     def exit_gracefully
+      # wait all workers to exit
       Process.waitall
+      # remove master process pid
       Merb::Server.remove_pid(&quot;main&quot;)
+      # terminate
       exit
     end
 
@@ -643,6 +646,7 @@ class Merb::BootLoader::LoadClasses &lt; Merb::BootLoader
         if Merb::Config[:console_trap]
           Merb.trap(&quot;INT&quot;) {}
         else
+          # send ABRT to worker on INT
           Merb.trap(&quot;INT&quot;) do
             Merb.logger.warn! &quot;Reaping Workers&quot;
             begin
@@ -718,7 +722,9 @@ class Merb::BootLoader::LoadClasses &lt; Merb::BootLoader
     # (Does not return.)
     #
     # @api private
-    def reap_workers(status = 0)
+    # @param status&lt;Integer&gt; The status code to exit with
+    # @param sig&lt;String&gt;     The signal to send to workers
+    def reap_workers(status = 0, sig = &quot;ABRT&quot;)
       Merb.exiting = true unless status == 128
 
       begin
@@ -731,7 +737,7 @@ class Merb::BootLoader::LoadClasses &lt; Merb::BootLoader
       ($WORKERS || []).each do |p|
         threads &lt;&lt; Thread.new do
           begin
-            Process.kill(&quot;ABRT&quot;, p)
+            Process.kill(sig, p)
             Process.wait2(p)
           rescue SystemCallError
           end</diff>
      <filename>lib/merb-core/bootloader.rb</filename>
    </modified>
    <modified>
      <diff>@@ -74,26 +74,23 @@ module Merb
       # processes.
       #
       # @api private
-      def kill(port, sig=&quot;INT&quot;)
+      def kill(port, sig = &quot;INT&quot;)
+        # 9 =&gt; KILL
+        # 2 =&gt; INT
+        if sig.is_a?(Integer)
+          sig = Signal.list.invert[sig]
+        end
+        
         Merb::BootLoader::BuildFramework.run
-        if sig == 9 &amp;&amp; port == &quot;main&quot;
-          kill_pid(&quot;INT&quot;, pid_file(&quot;main&quot;))
+        # assume that if we kill master,
+        # workers should be reaped, too
+        if %w(main all).include?(port)
           Dir[&quot;#{Merb.log_path}&quot; / &quot;*.pid&quot;].each do |file|
-            kill_pid(9, file)
+            kill_pid(sig, file)
           end
         else
           kill_pid(sig, pid_file(port))
         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
 
       # Kills the process pointed at by the provided pid file.
@@ -101,25 +98,28 @@ module Merb
       def kill_pid(sig, file)
         begin
           pid = File.read(file).chomp.to_i
-          Merb.logger.warn! &quot;Killing pid #{pid}&quot;
+          Merb.logger.fatal! &quot;Killing pid #{pid} with #{sig}&quot;
           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; \
+          Merb.fatal! &quot;Failed to kill PID #{pid} with #{sig}: '#{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;
+          Merb.fatal! &quot;Failed to kill PID #{pid} with #{sig}: Insufficient permissions.&quot;
         rescue Errno::ESRCH
           FileUtils.rm file
-          Merb.fatal! &quot;Failed to kill PID #{pid}: Process is &quot; \
+          Merb.fatal! &quot;Failed to kill PID #{pid} with #{sig}: Process is &quot; \
             &quot;deceased or zombie.&quot;
         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 #{file}&quot;, e
+          # This should not cause abnormal exit, that's why
+          # we do not use Merb.fatal but instead just
+          # log with max level.
+          Merb.logger.fatal! &quot;Could not find a PID file at #{file}. Probably process is no longer running but pid file wasn't cleaned up.&quot;, e
         rescue Exception =&gt; e
           if !e.is_a?(SystemExit)
-            Merb.fatal! &quot;Failed to kill PID #{pid}&quot;, e
+            Merb.fatal! &quot;Failed to kill PID #{pid} with #{sig}&quot;, e
           end
         end
       end
@@ -156,10 +156,7 @@ module Merb
       #
       # @api private
       def bootup
-        Merb.trap('TERM') {
-          Merb::BootLoader::LoadClasses.reap_workers if Merb::Config[:fork_for_class_load]
-          exit
-        }
+        Merb.trap('TERM') { shutdown }
 
         puts &quot;Running bootloaders...&quot; if Merb::Config[:verbose]
         BootLoader.run
@@ -170,6 +167,13 @@ module Merb
       # Change process user/group to those specified in Merb::Config.
       #
       # @api private
+      def shutdown(status = 0)
+        # reap_workers does exit but may not be called
+        Merb::BootLoader::LoadClasses.reap_workers(status) if Merb::Config[:fork_for_class_load]
+        # that's why we exit explicitly here
+        exit(status)
+      end
+
       def change_privilege
         if Merb::Config[:user] &amp;&amp; Merb::Config[:group]
           Merb.logger.verbose! &quot;About to change privilege to group &quot; \</diff>
      <filename>lib/merb-core/server.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>a68e147e759021d2e6ab1bd0e2d89fe4d9b1c2a1</id>
    </parent>
  </parents>
  <author>
    <name>Michael S. Klishin</name>
    <email>michael@novemberain.com</email>
  </author>
  <url>http://github.com/wycats/merb-core/commit/2d721c48372e8aaf85b5b6c4b653b83df0402915</url>
  <id>2d721c48372e8aaf85b5b6c4b653b83df0402915</id>
  <committed-date>2008-10-11T07:49:52-07:00</committed-date>
  <authored-date>2008-10-11T07:49:52-07:00</authored-date>
  <message>Merge upstream, re-apply stash.</message>
  <tree>0fa3912b71ee6f8d5266b56fc69b28848a7aa1f6</tree>
  <committer>
    <name>Michael S. Klishin</name>
    <email>michael@novemberain.com</email>
  </committer>
</commit>
