This class is capable of spawning Ruby on Rails application instances. Spawning a Ruby on Rails application is usually slow. But SpawnManager will preload and cache Ruby on Rails frameworks, as well as application code, so subsequent spawns will be very fast.

Internally, SpawnManager uses FrameworkSpawner to preload and cache Ruby on Rails frameworks. FrameworkSpawner, in turn, uses ApplicationSpawner to preload and cache application code.

Note: SpawnManager may only be started synchronously with AbstractServer#start_synchronously. Starting asynchronously has not been tested. Don‘t forget to call cleanup after the server‘s main loop has finished.

Methods
Included Modules
Constants
DEFAULT_INPUT_FD = 3
FRAMEWORK_SPAWNER_MAX_IDLE_TIME = 30 * 60
APP_SPAWNER_MAX_IDLE_TIME = FrameworkSpawner::APP_SPAWNER_MAX_IDLE_TIME
SPAWNER_CLEAN_INTERVAL = [FRAMEWORK_SPAWNER_MAX_IDLE_TIME, APP_SPAWNER_MAX_IDLE_TIME].min + 5
Public Class methods
new()
    # File lib/passenger/spawn_manager.rb, line 48
48:         def initialize
49:                 super()
50:                 @spawners = {}
51:                 @lock = Mutex.new
52:                 @cond = ConditionVariable.new
53:                 @cleaner_thread = Thread.new do
54:                         cleaner_thread_main
55:                 end
56:                 define_message_handler(:spawn_application, :handle_spawn_application)
57:                 define_message_handler(:reload, :handle_reload)
58:                 define_signal_handler('SIGHUP', :reload)
59:         end
Public Instance methods
cleanup()

Cleanup resources. Should be called when this SpawnManager is no longer needed.

     # File lib/passenger/spawn_manager.rb, line 165
165:         def cleanup
166:                 @lock.synchronize do
167:                         @cond.signal
168:                 end
169:                 @cleaner_thread.join
170:                 @lock.synchronize do
171:                         @spawners.each_value do |spawner|
172:                                 spawner.stop
173:                         end
174:                         @spawners.clear
175:                 end
176:         end
reload(app_root = nil)

Remove the cached application instances at the given application root. If nil is specified as application root, then all cached application instances will be removed, no matter the application root.

Long description: Application code might be cached in memory. But once it a while, it will be necessary to reload the code for an application, such as after deploying a new version of the application. This method makes sure that any cached application code is removed, so that the next time an application instance is spawned, the application code will be freshly loaded into memory.

Raises AbstractServer::SpawnError if something went wrong.

     # File lib/passenger/spawn_manager.rb, line 138
138:         def reload(app_root = nil)
139:                 if app_root
140:                         begin
141:                                 app_root = normalize_path(app_root)
142:                         rescue ArgumentError
143:                         end
144:                 end
145:                 @lock.synchronize do
146:                         if app_root
147:                                 # Delete associated ApplicationSpawner.
148:                                 key = "app:#{app_root}"
149:                                 spawner = @spawners[key]
150:                                 if spawner
151:                                         spawner.stop
152:                                         @spawners.delete(key)
153:                                 end
154:                         end
155:                         @spawners.each_value do |spawner|
156:                                 # Reload FrameworkSpawners.
157:                                 if spawner.respond_to?(:reload)
158:                                         spawner.reload(app_root)
159:                                 end
160:                         end
161:                 end
162:         end
spawn_application(app_root, lower_privilege = true, lowest_user = "nobody")

Spawn a RoR application When successful, an Application object will be returned, which represents the spawned RoR application.

See ApplicationSpawner.new for an explanation of the lower_privilege and lowest_user parameters.

SpawnManager will internally cache the code of applications, in order to speed up future spawning attempts. This implies that, if you‘ve changed the application‘s code, you must do one of these things:

Raises:

  • ArgumentError: app_root doesn‘t appear to be a valid Ruby on Rails application root.
  • VersionNotFound: The Ruby on Rails framework version that the given application requires is not installed.
  • AbstractServer::ServerError: One of the server processes exited unexpectedly.
  • FrameworkInitError: The Ruby on Rails framework that the application requires could not be loaded.
  • AppInitError: The application raised an exception or called exit() during startup.
     # File lib/passenger/spawn_manager.rb, line 80
 80:         def spawn_application(app_root, lower_privilege = true, lowest_user = "nobody")
 81:                 framework_version = Application.detect_framework_version(app_root)
 82:                 if framework_version == :vendor
 83:                         vendor_path = normalize_path("#{app_root}/vendor/rails")
 84:                         key = "vendor:#{vendor_path}"
 85:                         create_spawner = proc do
 86:                                 FrameworkSpawner.new(:vendor => vendor_path)
 87:                         end
 88:                 elsif framework_version.nil?
 89:                         app_root = normalize_path(app_root)
 90:                         key = "app:#{app_root}"
 91:                         create_spawner = proc do
 92:                                 ApplicationSpawner.new(app_root, lower_privilege, lowest_user)
 93:                         end
 94:                 else
 95:                         key = "version:#{framework_version}"
 96:                         create_spawner = proc do
 97:                                 FrameworkSpawner.new(:version => framework_version)
 98:                         end
 99:                 end
100:                 
101:                 spawner = nil
102:                 @lock.synchronize do
103:                         spawner = @spawners[key]
104:                         if !spawner
105:                                 spawner = create_spawner.call
106:                                 spawner.start
107:                                 @spawners[key] = spawner
108:                         end
109:                         spawner.time = Time.now
110:                         begin
111:                                 if spawner.is_a?(FrameworkSpawner)
112:                                         return spawner.spawn_application(app_root, lower_privilege,
113:                                                 lowest_user)
114:                                 else
115:                                         return spawner.spawn_application
116:                                 end
117:                         rescue AbstractServer::ServerError
118:                                 spawner.stop
119:                                 @spawners.delete(key)
120:                                 raise
121:                         end
122:                 end
123:         end