This class is capable of spawns instances of a single Ruby on Rails application. It does so by preloading as much of the application‘s code as possible, then creating instances of the application using what is already preloaded. This makes it spawning application instances very fast, except for the first spawn.
Use multiple instances of ApplicationSpawner if you need to spawn multiple different Ruby on Rails applications.
Note: ApplicationSpawner may only be started asynchronously with AbstractServer#start. Starting it synchronously with AbstractServer#start_synchronously has not been tested.
| ROOT_UID | = | 0 |
| The user ID of the root user. | ||
| ROOT_GID | = | 0 |
| The group ID of the root user. | ||
| [R] | app_root | The application root of this spawner. |
| [RW] | time | An attribute, used internally. This should not be used outside Passenger. |
app_root is the root directory of this application, i.e. the directory that contains ‘app/’, ‘public/’, etc. If given an invalid directory, or a directory that doesn‘t appear to be a Rails application root directory, then an ArgumentError will be raised.
If lower_privilege is true, then ApplicationSpawner will attempt to switch to the user who owns the application‘s config/environment.rb, and to the default group of that user.
If that user doesn‘t exist on the system, or if that user is root, then ApplicationSpawner will attempt to switch to the username given by lowest_user (and to the default group of that user). If lowest_user doesn‘t exist either, or if switching user failed (because the current process does not have the privilege to do so), then ApplicationSpawner will continue without reporting an error.
[ show source ]
# File lib/passenger/application_spawner.rb, line 105
105: def initialize(app_root, lower_privilege = true, lowest_user = "nobody")
106: super()
107: begin
108: @app_root = normalize_path(app_root)
109: rescue SystemCallError => e
110: raise ArgumentError, e.message
111: rescue ArgumentError
112: raise
113: end
114: @lower_privilege = lower_privilege
115: @lowest_user = lowest_user
116: self.time = Time.now
117: assert_valid_app_root(@app_root)
118: define_message_handler(:spawn_application, :handle_spawn_application)
119: end
Spawn an instance of the RoR application. When successful, an Application object will be returned, which represents the spawned RoR application.
Raises:
- AbstractServer::ServerNotStarted: The ApplicationSpawner server hasn‘t already been started.
- ApplicationSpawner::Error: The ApplicationSpawner server exited unexpectedly.
[ show source ]
# File lib/passenger/application_spawner.rb, line 127
127: def spawn_application
128: server.write("spawn_application")
129: pid, socket_name, using_abstract_namespace = server.read
130: if pid.nil?
131: raise IOError, "Connection closed"
132: end
133: owner_pipe = server.recv_io
134: return Application.new(@app_root, pid, socket_name,
135: using_abstract_namespace == "true", owner_pipe)
136: rescue SystemCallError, IOError, SocketError => e
137: raise Error, "The application spawner server exited unexpectedly"
138: end
Overrided from AbstractServer#start.
May raise these additional exceptions:
- AppInitError: The Ruby on Rails application raised an exception or called exit() during startup.
- ApplicationSpawner::Error: The ApplicationSpawner server exited unexpectedly.
[ show source ]
# File lib/passenger/application_spawner.rb, line 146
146: def start
147: super
148: begin
149: status = server.read[0]
150: if status == 'exception'
151: child_exception = unmarshal_exception(server.read_scalar)
152: stop
153: raise AppInitError.new(
154: "Application '#{@app_root}' raised an exception: " <<
155: "#{child_exception.class} (#{child_exception.message})",
156: child_exception)
157: elsif status == 'exit'
158: stop
159: raise AppInitError.new("Application '#{@app_root}' exited during startup")
160: end
161: rescue IOError, SystemCallError, SocketError
162: stop
163: raise Error, "The application spawner server exited unexpectedly"
164: end
165: end