public
Rubygem
Description: Merb Core: All you need. None you don't.
Homepage: http://www.merbivore.com
Clone URL: git://github.com/wycats/merb-core.git
Merge upstream, re-apply stash.
Sat Oct 11 07:49:52 -0700 2008
commit  2d721c48372e8aaf85b5b6c4b653b83df0402915
tree    0fa3912b71ee6f8d5266b56fc69b28848a7aa1f6
parent  a68e147e759021d2e6ab1bd0e2d89fe4d9b1c2a1
...
566
567
568
569
 
570
571
572
...
600
601
602
 
603
 
604
 
605
606
607
...
643
644
645
 
646
647
648
...
718
719
720
721
 
 
 
722
723
724
...
731
732
733
734
 
735
736
737
...
566
567
568
 
569
570
571
572
...
600
601
602
603
604
605
606
607
608
609
610
...
646
647
648
649
650
651
652
...
722
723
724
 
725
726
727
728
729
730
...
737
738
739
 
740
741
742
743
0
@@ -566,7 +566,7 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
0
 
0
       # Log the process configuration user defined signal 1 (SIGUSR1) is received.
0
       Merb.trap("USR1") do
0
-        Merb.logger.error! "Configuration:\n#{Merb::Config.to_hash.merge(:pid => $$).to_yaml}\n\n"
0
+        Merb.logger.fatal! "Configuration:\n#{Merb::Config.to_hash.merge(:pid => $$).to_yaml}\n\n"
0
       end
0
 
0
       if Merb::Config[:fork_for_class_load] && !Merb.testing?
0
@@ -600,8 +600,11 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
0
     #
0
     # @api private
0
     def exit_gracefully
0
+      # wait all workers to exit
0
       Process.waitall
0
+      # remove master process pid
0
       Merb::Server.remove_pid("main")
0
+      # terminate
0
       exit
0
     end
0
 
0
@@ -643,6 +646,7 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
0
         if Merb::Config[:console_trap]
0
           Merb.trap("INT") {}
0
         else
0
+          # send ABRT to worker on INT
0
           Merb.trap("INT") do
0
             Merb.logger.warn! "Reaping Workers"
0
             begin
0
@@ -718,7 +722,9 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
0
     # (Does not return.)
0
     #
0
     # @api private
0
-    def reap_workers(status = 0)
0
+    # @param status<Integer> The status code to exit with
0
+    # @param sig<String>     The signal to send to workers
0
+    def reap_workers(status = 0, sig = "ABRT")
0
       Merb.exiting = true unless status == 128
0
 
0
       begin
0
@@ -731,7 +737,7 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
0
       ($WORKERS || []).each do |p|
0
         threads << Thread.new do
0
           begin
0
-            Process.kill("ABRT", p)
0
+            Process.kill(sig, p)
0
             Process.wait2(p)
0
           rescue SystemCallError
0
           end
...
74
75
76
77
 
 
 
 
 
 
 
78
79
80
 
 
 
81
82
 
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
...
101
102
103
104
 
105
106
107
108
 
109
110
111
 
112
113
114
 
115
116
117
118
119
 
 
 
 
120
121
122
 
123
124
125
...
156
157
158
159
160
161
162
 
163
164
165
...
170
171
172
 
 
 
 
 
 
 
173
174
175
...
74
75
76
 
77
78
79
80
81
82
83
84
 
 
85
86
87
88
 
89
90
91
92
93
 
 
 
 
 
 
 
 
 
 
94
95
96
...
98
99
100
 
101
102
103
104
 
105
106
107
 
108
109
110
 
111
112
113
114
115
 
116
117
118
119
120
121
 
122
123
124
125
...
156
157
158
 
 
 
 
159
160
161
162
...
167
168
169
170
171
172
173
174
175
176
177
178
179
0
@@ -74,26 +74,23 @@ module Merb
0
       # processes.
0
       #
0
       # @api private
0
-      def kill(port, sig="INT")
0
+      def kill(port, sig = "INT")
0
+        # 9 => KILL
0
+        # 2 => INT
0
+        if sig.is_a?(Integer)
0
+          sig = Signal.list.invert[sig]
0
+        end
0
+        
0
         Merb::BootLoader::BuildFramework.run
0
-        if sig == 9 && port == "main"
0
-          kill_pid("INT", pid_file("main"))
0
+        # assume that if we kill master,
0
+        # workers should be reaped, too
0
+        if %w(main all).include?(port)
0
           Dir["#{Merb.log_path}" / "*.pid"].each do |file|
0
-            kill_pid(9, file)
0
+            kill_pid(sig, file)
0
           end
0
         else
0
           kill_pid(sig, pid_file(port))
0
         end
0
-
0
-        if sig.is_a?(Integer)
0
-          sig = Signal.list.invert[sig]
0
-        end
0
-
0
-        if sig == "KILL" && port == "main"
0
-          Merb.fatal! "Killed all PIDs with signal KILL"
0
-        else
0
-          Merb.fatal! "Killed #{port} with signal #{sig}"
0
-        end
0
       end
0
 
0
       # Kills the process pointed at by the provided pid file.
0
@@ -101,25 +98,28 @@ module Merb
0
       def kill_pid(sig, file)
0
         begin
0
           pid = File.read(file).chomp.to_i
0
-          Merb.logger.warn! "Killing pid #{pid}"
0
+          Merb.logger.fatal! "Killing pid #{pid} with #{sig}"
0
           Process.kill(sig, pid)
0
           FileUtils.rm(file) if File.exist?(file)
0
         rescue Errno::EINVAL
0
-          Merb.fatal! "Failed to kill PID #{pid}: '#{sig}' is an invalid " \
0
+          Merb.fatal! "Failed to kill PID #{pid} with #{sig}: '#{sig}' is an invalid " \
0
             "or unsupported signal number."
0
         rescue Errno::EPERM
0
-          Merb.fatal! "Failed to kill PID #{pid}: Insufficient permissions."
0
+          Merb.fatal! "Failed to kill PID #{pid} with #{sig}: Insufficient permissions."
0
         rescue Errno::ESRCH
0
           FileUtils.rm file
0
-          Merb.fatal! "Failed to kill PID #{pid}: Process is " \
0
+          Merb.fatal! "Failed to kill PID #{pid} with #{sig}: Process is " \
0
             "deceased or zombie."
0
         rescue Errno::EACCES => e
0
           Merb.fatal! e.message, e
0
         rescue Errno::ENOENT => e
0
-          Merb.fatal! "Could not find a PID file at #{file}", e
0
+          # This should not cause abnormal exit, that's why
0
+          # we do not use Merb.fatal but instead just
0
+          # log with max level.
0
+          Merb.logger.fatal! "Could not find a PID file at #{file}. Probably process is no longer running but pid file wasn't cleaned up.", e
0
         rescue Exception => e
0
           if !e.is_a?(SystemExit)
0
-            Merb.fatal! "Failed to kill PID #{pid}", e
0
+            Merb.fatal! "Failed to kill PID #{pid} with #{sig}", e
0
           end
0
         end
0
       end
0
@@ -156,10 +156,7 @@ module Merb
0
       #
0
       # @api private
0
       def bootup
0
-        Merb.trap('TERM') {
0
-          Merb::BootLoader::LoadClasses.reap_workers if Merb::Config[:fork_for_class_load]
0
-          exit
0
-        }
0
+        Merb.trap('TERM') { shutdown }
0
 
0
         puts "Running bootloaders..." if Merb::Config[:verbose]
0
         BootLoader.run
0
@@ -170,6 +167,13 @@ module Merb
0
       # Change process user/group to those specified in Merb::Config.
0
       #
0
       # @api private
0
+      def shutdown(status = 0)
0
+        # reap_workers does exit but may not be called
0
+        Merb::BootLoader::LoadClasses.reap_workers(status) if Merb::Config[:fork_for_class_load]
0
+        # that's why we exit explicitly here
0
+        exit(status)
0
+      end
0
+
0
       def change_privilege
0
         if Merb::Config[:user] && Merb::Config[:group]
0
           Merb.logger.verbose! "About to change privilege to group " \

Comments