We got nominated! Help us out and vote for GitHub as Best Bootstrapped Startup of 2008. (You can vote once a day.) [ hide ]

public
Description: Phusion Passenger (mod_rails)
Homepage: http://www.modrails.com/
Clone URL: git://github.com/FooBarWidget/passenger.git
Click here to lend your support to: passenger and make a donation at www.pledgie.com !
Close unnecessary file descriptors when spawning Rack and WSGI 
applications, and Rails applications in conservative mode.
Hongli Lai (Phusion) (author)
Wed Nov 19 09:20:56 -0800 2008
commit  2434de04c45846e20293418aea42d54bc13abbaf
tree    86832d2ef15a6ac8fe8071c3160f954cf6d96a4a
parent  ddf382fbaccc7f52bf142de5178aefcce68fe9b9
...
49
50
51
52
53
54
55
56
57
 
 
 
 
 
 
 
 
58
59
60
...
49
50
51
 
 
 
 
 
 
52
53
54
55
56
57
58
59
60
61
62
0
@@ -49,12 +49,14 @@ class ApplicationSpawner
0
     }.merge(options)
0
     
0
     a, b = UNIXSocket.pair
0
- # Double fork in order to prevent zombie processes.
0
- pid = safe_fork(self.class.to_s) do
0
- safe_fork(self.class.to_s) do
0
- a.close
0
- run(MessageChannel.new(b), app_root, options)
0
- end
0
+ pid = safe_fork(self.class.to_s, true) do
0
+ a.close
0
+
0
+ file_descriptors_to_leave_open = [0, 1, 2, b.fileno]
0
+ NativeSupport.close_all_file_descriptors(file_descriptors_to_leave_open)
0
+ close_all_io_objects_for_fds(file_descriptors_to_leave_open)
0
+
0
+ run(MessageChannel.new(b), app_root, options)
0
     end
0
     b.close
0
     Process.waitpid(pid) rescue nil
...
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
 
 
 
 
 
 
 
 
 
 
 
162
163
164
...
134
135
136
 
137
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
0
@@ -134,31 +134,33 @@ class ApplicationSpawner < AbstractServer
0
   # or called exit() during startup.
0
   # - SystemCallError, IOError, SocketError: Something went wrong.
0
   def spawn_application!
0
- # Double fork to prevent zombie processes.
0
     a, b = UNIXSocket.pair
0
- pid = safe_fork(self.class.to_s) do
0
- safe_fork('application') do
0
- begin
0
- a.close
0
- channel = MessageChannel.new(b)
0
- success = report_app_init_status(channel) do
0
- ENV['RAILS_ENV'] = @environment
0
- Dir.chdir(@app_root)
0
- if @lower_privilege
0
- lower_privilege('config/environment.rb', @lowest_user)
0
- end
0
- remove_phusion_passenger_namespace
0
- require 'config/environment'
0
- require 'dispatcher'
0
- end
0
- if success
0
- start_request_handler(channel)
0
- end
0
- rescue SignalException => e
0
- if e.message != AbstractRequestHandler::HARD_TERMINATION_SIGNAL &&
0
- e.message != AbstractRequestHandler::SOFT_TERMINATION_SIGNAL
0
- raise
0
+ pid = safe_fork('application', true) do
0
+ begin
0
+ a.close
0
+
0
+ file_descriptors_to_leave_open = [0, 1, 2, b.fileno]
0
+ NativeSupport.close_all_file_descriptors(file_descriptors_to_leave_open)
0
+ close_all_io_objects_for_fds(file_descriptors_to_leave_open)
0
+
0
+ channel = MessageChannel.new(b)
0
+ success = report_app_init_status(channel) do
0
+ ENV['RAILS_ENV'] = @environment
0
+ Dir.chdir(@app_root)
0
+ if @lower_privilege
0
+ lower_privilege('config/environment.rb', @lowest_user)
0
           end
0
+ remove_phusion_passenger_namespace
0
+ require 'config/environment'
0
+ require 'dispatcher'
0
+ end
0
+ if success
0
+ start_request_handler(channel)
0
+ end
0
+ rescue SignalException => e
0
+ if e.message != AbstractRequestHandler::HARD_TERMINATION_SIGNAL &&
0
+ e.message != AbstractRequestHandler::SOFT_TERMINATION_SIGNAL
0
+ raise
0
         end
0
       end
0
     end
...
188
189
190
191
 
192
193
194
...
188
189
190
 
191
192
193
194
0
@@ -188,7 +188,7 @@ protected
0
       end
0
     else
0
       if double_fork
0
- Process.waitpid(pid)
0
+ Process.waitpid(pid) rescue nil
0
         return pid
0
       else
0
         return pid
...
41
42
43
44
45
46
47
48
49
 
 
 
 
 
 
 
 
50
51
52
...
41
42
43
 
 
 
 
 
 
44
45
46
47
48
49
50
51
52
53
54
0
@@ -41,12 +41,14 @@ class ApplicationSpawner
0
   # - SystemCallError, IOError, SocketError: Something went wrong.
0
   def spawn_application(app_root, lower_privilege = true, lowest_user = "nobody", environment = "production")
0
     a, b = UNIXSocket.pair
0
- # Double fork in order to prevent zombie processes.
0
- pid = safe_fork(self.class.to_s) do
0
- safe_fork(self.class.to_s) do
0
- a.close
0
- run(MessageChannel.new(b), app_root, lower_privilege, lowest_user, environment)
0
- end
0
+ pid = safe_fork(self.class.to_s, true) do
0
+ a.close
0
+
0
+ file_descriptors_to_leave_open = [0, 1, 2, b.fileno]
0
+ NativeSupport.close_all_file_descriptors(file_descriptors_to_leave_open)
0
+ close_all_io_objects_for_fds(file_descriptors_to_leave_open)
0
+
0
+ run(MessageChannel.new(b), app_root, lower_privilege, lowest_user, environment)
0
     end
0
     b.close
0
     Process.waitpid(pid) rescue nil

Comments

  • Hi Hongli,
    Would this fix a problem I’m seeing at the moment where old idle Rails processes don’t die ? They just hang around forever, I don’t have the idle time specified.
    (I’m using the github revision before this commit)

  • Maybe but I’m not sure, it depends on the cause of the problem. I’d say, try it out.