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 !
Our 'Passenger' namespace may conflict with application models that happen 
to be named 'Passenger' as well. Fix this.
Hongli Lai (Phusion) (author)
Wed Jul 16 04:28:18 -0700 2008
commit  cd4f229c769848e9bae353d002a40d82fb648ce2
tree    b4a6d7ce565891915f928812664672a844ce199c
parent  c346244b221facd206253e48becb9e16f06bf5ba
...
146
147
148
 
 
 
 
 
 
 
149
150
151
...
180
181
182
 
 
 
 
183
184
185
...
146
147
148
149
150
151
152
153
154
155
156
157
158
...
187
188
189
190
191
192
193
194
195
196
0
@@ -146,6 +146,13 @@ class AbstractRequestHandler
0
   
0
   # Enter the request handler's main loop.
0
   def main_loop
0
+ if defined?(::Passenger::AbstractRequestHandler)
0
+ # Some applications have a model named 'Passenger'.
0
+ # So we temporarily remove it from the global namespace
0
+ # and restore it later.
0
+ phusion_passenger_namespace = ::Passenger
0
+ Object.send(:remove_const, :Passenger)
0
+ end
0
     reset_signal_handlers
0
     begin
0
       done = false
0
@@ -180,6 +187,10 @@ class AbstractRequestHandler
0
       end
0
     ensure
0
       revert_signal_handlers
0
+ if phusion_passenger_namespace
0
+ Object.send(:remove_const, :Passenger) rescue nil
0
+ Object.const_set(:Passenger, phusion_passenger_namespace)
0
+ end
0
     end
0
   end
0
 
...
77
78
79
 
80
81
82
...
77
78
79
80
81
82
83
0
@@ -77,6 +77,7 @@ private
0
       if lower_privilege
0
         lower_privilege('config.ru', lowest_user)
0
       end
0
+ remove_phusion_passenger_namespace
0
       app = load_rack_app
0
     end
0
     
...
22
23
24
 
25
26
27
...
135
136
137
 
138
139
140
...
207
208
209
 
210
211
212
...
22
23
24
25
26
27
28
...
136
137
138
139
140
141
142
...
209
210
211
212
213
214
215
0
@@ -22,6 +22,7 @@ require 'etc'
0
 require 'passenger/application'
0
 require 'passenger/abstract_server'
0
 require 'passenger/application'
0
+require 'passenger/constants'
0
 require 'passenger/railz/request_handler'
0
 require 'passenger/exceptions'
0
 require 'passenger/utils'
0
@@ -135,6 +136,7 @@ class ApplicationSpawner < AbstractServer
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
@@ -207,6 +209,7 @@ protected
0
       if @lower_privilege
0
         lower_privilege('config/environment.rb', @lowest_user)
0
       end
0
+ remove_phusion_passenger_namespace
0
       preload_application
0
     end
0
   end
...
143
144
145
146
 
 
 
 
 
147
148
149
...
209
210
211
 
212
213
214
...
143
144
145
 
146
147
148
149
150
151
152
153
...
213
214
215
216
217
218
219
0
@@ -143,7 +143,11 @@ class FrameworkSpawner < AbstractServer
0
         raise IOError, "Connection closed"
0
       end
0
       if result[0] == 'exception'
0
- raise unmarshal_exception(server.read_scalar)
0
+ e = unmarshal_exception(server.read_scalar)
0
+ if e.respond_to?(:child_exception) && e.child_exception
0
+ #print_exception(self.class.to_s, e.child_exception)
0
+ end
0
+ raise e
0
       else
0
         pid, listen_socket_name, using_abstract_namespace = server.read
0
         if pid.nil?
0
@@ -209,6 +213,7 @@ protected
0
     end
0
     begin
0
       preload_rails
0
+ remove_phusion_passenger_namespace
0
     rescue StandardError, ScriptError, NoMemoryError => e
0
       client.write('exception')
0
       client.write_scalar(marshal_exception(e))
...
19
20
21
 
 
 
 
 
 
22
23
24
...
19
20
21
22
23
24
25
26
27
28
29
30
0
@@ -19,6 +19,12 @@
0
 require 'passenger/abstract_server'
0
 require 'passenger/constants'
0
 require 'passenger/utils'
0
+
0
+# Define a constant with a name that's unlikely to clash with anything the
0
+# application defines, so that they can detect whether they're running under
0
+# Phusion Passenger.
0
+IN_PHUSION_PASSENGER = true
0
+
0
 module Passenger
0
 
0
 # The spawn manager is capable of spawning Ruby on Rails or Rack application
...
33
34
35
 
 
36
37
38
...
96
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
...
268
269
270
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
271
272
273
...
33
34
35
36
37
38
39
40
...
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
...
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
0
@@ -33,6 +33,8 @@ module Passenger
0
 # Utility functions.
0
 module Utils
0
 protected
0
+ GENUINE_PHUSION_PASSENGER_NAMESPACE = Passenger
0
+
0
   # Return the absolute version of +path+. This path is guaranteed to
0
   # to be "normal", i.e. it doesn't contain stuff like ".." or "/",
0
   # and it correctly respects symbolic links.
0
@@ -96,26 +98,28 @@ protected
0
   end
0
   
0
   def marshal_exception(exception)
0
- data = {
0
- :message => exception.message,
0
- :class => exception.class.to_s,
0
- :backtrace => exception.backtrace
0
- }
0
- if exception.is_a?(InitializationError)
0
- data[:is_initialization_error] = true
0
- if exception.child_exception
0
- data[:child_exception] = marshal_exception(exception.child_exception)
0
- end
0
- else
0
- begin
0
- data[:exception] = Marshal.dump(exception)
0
- rescue ArgumentError, TypeError
0
- e = UnknownError.new(exception.message, exception.class.to_s,
0
- exception.backtrace)
0
- data[:exception] = Marshal.dump(e)
0
+ temporarily_restore_phusion_passenger_namespace do
0
+ data = {
0
+ :message => exception.message,
0
+ :class => exception.class.to_s,
0
+ :backtrace => exception.backtrace
0
+ }
0
+ if exception.is_a?(InitializationError)
0
+ data[:is_initialization_error] = true
0
+ if exception.child_exception
0
+ data[:child_exception] = marshal_exception(exception.child_exception)
0
+ end
0
+ else
0
+ begin
0
+ data[:exception] = Marshal.dump(exception)
0
+ rescue ArgumentError, TypeError
0
+ e = UnknownError.new(exception.message, exception.class.to_s,
0
+ exception.backtrace)
0
+ data[:exception] = Marshal.dump(e)
0
+ end
0
       end
0
+ return Marshal.dump(data)
0
     end
0
- return Marshal.dump(data)
0
   end
0
   
0
   def unmarshal_exception(data)
0
@@ -268,6 +272,35 @@ protected
0
       return true
0
     end
0
   end
0
+
0
+ # Some applications have a model named 'Passenger'.
0
+ # This method removes the Passenger module from the
0
+ # global namespace.
0
+ def remove_phusion_passenger_namespace
0
+ if defined?(::Passenger) && ::Passenger == GENUINE_PHUSION_PASSENGER_NAMESPACE
0
+ Object.send(:remove_const, :Passenger)
0
+ end
0
+ end
0
+
0
+ # The current 'Passenger' namespace might be reserved by an application.
0
+ # This method temporarily restores the 'Passenger' namespace to that of
0
+ # Phusion Passenger's, runs the block, then restores the 'Passenger'
0
+ # namespace back to what it was before.
0
+ def temporarily_restore_phusion_passenger_namespace
0
+ if defined?(::Passenger)
0
+ old_passenger_namespace = ::Passenger
0
+ Object.send(:remove_const, :Passenger)
0
+ end
0
+ Object.const_set(:Passenger, GENUINE_PHUSION_PASSENGER_NAMESPACE)
0
+ begin
0
+ yield
0
+ ensure
0
+ Object.send(:remove_const, :Passenger)
0
+ if old_passenger_namespace
0
+ Object.const_set(:Passenger, old_passenger_namespace)
0
+ end
0
+ end
0
+ end
0
 end
0
 
0
 end # module Passenger
...
124
125
126
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
128
129
...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
0
@@ -124,6 +124,23 @@ shared_examples_for "MyCook(tm) beta" do
0
     get('/').should =~ /Welcome to MyCook/
0
   end
0
   
0
+ it "does not conflict with Phusion Passenger is there's a model named 'Passenger'" do
0
+ File.open("#{@stub.app_root}/app/models/passenger.rb", 'w') do |f|
0
+ f.write(%q{
0
+ class Passenger
0
+ def name
0
+ return "Gourry Gabriev"
0
+ end
0
+ end
0
+ })
0
+ end
0
+ begin
0
+ get('/welcome/passenger_name').should == 'Gourry Gabriev'
0
+ ensure
0
+ File.unlink("#{@stub.app_root}/app/models/passenger.rb") rescue nil
0
+ end
0
+ end
0
+
0
   if Process.uid == 0
0
     it "runs as an unprivileged user" do
0
       post('/welcome/touch')
...
34
35
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
...
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
0
@@ -34,4 +34,30 @@ shared_examples_for "a minimal spawner" do
0
       environment.should == "development"
0
     end
0
   end
0
+
0
+ it "does not conflict with models in the application that are named 'Passenger'" do
0
+ use_rails_stub('foobar') do |stub|
0
+ File.open("#{stub.app_root}/app/models/passenger.rb", 'w') do |f|
0
+ f.write(%q{
0
+ class Passenger
0
+ def name
0
+ return "Gourry Gabriev"
0
+ end
0
+ end
0
+ })
0
+ end
0
+ File.append(stub.environment_rb, %q{
0
+ # We explicitly call 'require' here because we might be
0
+ # using a stub Rails framework (that doesn't support automatic
0
+ # loading of model source files).
0
+ require 'app/models/passenger'
0
+ File.open('passenger.txt', 'w') do |f|
0
+ f.write(Passenger.new.name)
0
+ end
0
+ })
0
+ spawn_stub_application(stub).close
0
+ passenger_name = File.read("#{stub.app_root}/passenger.txt")
0
+ passenger_name.should == 'Gourry Gabriev'
0
+ end
0
+ end
0
 end
...
18
19
20
21
 
22
23
24
...
29
30
31
 
 
 
 
32
33
34
...
18
19
20
 
21
22
23
24
...
29
30
31
32
33
34
35
36
37
38
0
@@ -18,7 +18,7 @@ class WelcomeController < ApplicationController
0
   end
0
   
0
   def in_passenger
0
- render :text => !!defined?(Passenger::SpawnManager)
0
+ render :text => !!defined?(IN_PHUSION_PASSENGER)
0
   end
0
   
0
   def rails_env
0
@@ -29,6 +29,10 @@ class WelcomeController < ApplicationController
0
     render :text => caller.join("\n")
0
   end
0
   
0
+ def passenger_name
0
+ render :text => Passenger.new.name
0
+ end
0
+
0
   def terminate
0
     exit!
0
   end

Comments

    No one has commented yet.