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
(put my Frankenstein voice on) It's alive!
Sat Oct 11 20:58:20 -0700 2008
commit  20fd63f05d75d10f8a6afc54c2295da259d89f78
tree    3a9822e7340c15f2c8eaeea43dbd864d98cd119c
parent  2d721c48372e8aaf85b5b6c4b653b83df0402915
...
562
563
564
 
565
566
567
...
604
605
606
607
 
 
608
609
610
...
632
633
634
 
635
636
637
...
640
641
642
643
 
644
645
646
...
562
563
564
565
566
567
568
...
605
606
607
 
608
609
610
611
612
...
634
635
636
637
638
639
640
...
643
644
645
 
646
647
648
649
0
@@ -562,6 +562,7 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
0
       end
0
 
0
       @ran = true
0
+      # process name you see in ps output
0
       $0 = "merb#{" : " + Merb::Config[:name] if Merb::Config[:name]} : master"
0
 
0
       # Log the process configuration user defined signal 1 (SIGUSR1) is received.
0
@@ -604,7 +605,8 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
0
       Process.waitall
0
       # remove master process pid
0
       Merb::Server.remove_pid("main")
0
-      # terminate
0
+      # terminate, workers remove their own pids
0
+      # in on exit hook
0
       exit
0
     end
0
 
0
@@ -632,6 +634,7 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
0
 
0
       loop do
0
         # create two connected endpoints
0
+        # we use them for master/workers communication
0
         reader, @writer = IO.pipe
0
         pid = Kernel.fork
0
 
0
@@ -640,7 +643,7 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
0
         # writer must be closed so reader can generate EOF condition
0
         @writer.close
0
 
0
-        # master process stores pid to merb.mail.pid
0
+        # master process stores pid to merb.main.pid
0
         Merb::Server.store_pid("main")
0
 
0
         if Merb::Config[:console_trap]
...
52
53
54
55
56
57
58
59
 
60
61
62
63
64
65
 
 
 
 
 
66
67
68
...
84
85
86
87
88
89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
91
92
...
97
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
...
52
53
54
 
55
 
 
 
56
57
58
59
60
61
 
62
63
64
65
66
67
68
69
...
85
86
87
 
 
 
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
...
121
122
123
 
124
125
126
127
128
 
129
130
131
 
132
133
134
 
135
136
137
 
138
139
140
141
142
 
143
144
145
 
146
147
148
149
0
@@ -52,17 +52,18 @@ module Merb
0
       #
0
       # @api private
0
       def alive?(port)
0
-        puts "About to check if port #{port} is alive..." if Merb::Config[:verbose]
0
         pidfile = pid_file(port)
0
-        puts "Pidfile is #{pidfile}..." if Merb::Config[:verbose]
0
-        pid = File.read(pidfile).chomp.to_i
0
-        puts "Process id is #{pid}" if Merb::Config[:verbose]
0
+        pid     = pid_in_file(pidfile)
0
         Process.kill(0, pid)
0
         true
0
       rescue Errno::ESRCH, Errno::ENOENT
0
         false
0
       rescue Errno::EACCES => e
0
-        Merb.fatal!("You don't have access to the PID file at #{pidfile}.", e)
0
+        Merb.fatal!("You don't have access to the PID file at #{pidfile}: #{e.message}")
0
+      end
0
+
0
+      def pid_in_file(pidfile)
0
+        File.read(pidfile).chomp.to_i
0
       end
0
 
0
       # ==== Parameters
0
@@ -84,9 +85,32 @@ module Merb
0
         Merb::BootLoader::BuildFramework.run
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(sig, file)
0
+        if %w(main master all).include?(port)
0
+          # if graceful exit is requested,
0
+          # send INT to master process and
0
+          # it's gonna do it's job
0
+          #
0
+          # Otherwise read pids from pid files
0
+          # and try to kill each process in
0
+          # turn
0
+          if sig == "INT"
0
+            kill_pid(sig, pid_file("main"))
0
+          else
0
+            # order is important here
0
+            
0
+            # then reap workers
0
+            # 
0
+            # there is no way to handle KILL so
0
+            # at_exit block does not work and
0
+            # processes do not clean up their
0
+            # pid files: lets do it ourselves
0
+            Dir["#{Merb.log_path}" / "*.pid"].each do |file|
0
+              kill_pid(sig, file)
0
+              ::FileUtils.rm_rf file
0
+            end
0
+
0
+            # reap master
0
+            kill_pid(sig, pid_file("main"))
0
           end
0
         else
0
           kill_pid(sig, pid_file(port))
0
@@ -97,29 +121,29 @@ module Merb
0
       # @api private
0
       def kill_pid(sig, file)
0
         begin
0
-          pid = File.read(file).chomp.to_i
0
+          pid = pid_in_file(file)
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} with #{sig}: '#{sig}' is an invalid " \
0
+          Merb.logger.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} with #{sig}: Insufficient permissions."
0
+          Merb.logger.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} with #{sig}: Process is " \
0
+          Merb.logger.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
+          Merb.logger.fatal! e.message
0
         rescue Errno::ENOENT => 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
+          Merb.logger.fatal! "Could not find a PID file at #{file}. Probably process is no longer running but pid file wasn't cleaned up."
0
         rescue Exception => e
0
           if !e.is_a?(SystemExit)
0
-            Merb.fatal! "Failed to kill PID #{pid} with #{sig}", e
0
+            Merb.logger.fatal! "Failed to kill PID #{pid.inspect} with #{sig.inspect}: #{e.message}"
0
           end
0
         end
0
       end

Comments