Class: PhusionPassenger::ClassicRails::ApplicationSpawner

Inherits:
AbstractServer show all
Extended by:
Utils
Includes:
DebugLogging, Utils
Defined in:
lib/phusion_passenger/classic_rails/application_spawner.rb

Overview

Spawning of Rails 1 and Rails 2 applications.

ClassicRails::ApplicationSpawner can operate in two modes:

  • Smart mode. In this mode, the Rails application’s code is first preloaded into a temporary process, which can then further fork off application processes. Once the code has been preloaded, forking off application processes is very fast, and all the forked off application processes can share code memory with each other. To use this mode, create an ApplicationSpawner object, start it, and call #spawn_application on it. A single ApplicationSpawner object can only handle a single Rails application.

  • Conservative mode. In this mode, a Rails app process is directly spawned without any preloading. This increases compatibility with applications. To use this mode, call ApplicationSpawner.spawn_application.

Defined Under Namespace

Classes: Error

Instance Attribute Summary collapse

Attributes inherited from AbstractServer

#ignore_password_errors, #max_idle_time, #next_cleaning_time, #password

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utils

process_is_alive?

Methods included from DebugLogging

_log_device, debug, error, included, log_file=, log_level=, stderr_evaluator=, trace, warn

Methods inherited from AbstractServer

#connect, #server_pid, #start_synchronously, #started?, #stop

Constructor Details

#initialize(options) ⇒ ApplicationSpawner

The following options are accepted:

  • ‘app_root’

See SpawnManager#spawn_application for information about the options.



116
117
118
119
120
121
122
123
# File 'lib/phusion_passenger/classic_rails/application_spawner.rb', line 116

def initialize(options)
	super()
	@options          = sanitize_spawn_options(options)
	@app_root         = @options["app_root"]
	@canonicalized_app_root = canonicalize_path(@app_root)
	self.max_idle_time = DEFAULT_APP_SPAWNER_MAX_IDLE_TIME
	define_message_handler(:spawn_application, :handle_spawn_application)
end

Instance Attribute Details

#app_rootObject (readonly)

The application root of this spawner.



64
65
66
# File 'lib/phusion_passenger/classic_rails/application_spawner.rb', line 64

def app_root
  @app_root
end

Class Method Details

.spawn_application(options) ⇒ Object

Spawns an instance of a Rails application. When successful, an AppProcess object will be returned, which represents the spawned Rails application.

This method spawns the application directly, without preloading its code. This method may only be called if no Rails framework has been loaded in the current Ruby VM.

The “app_root” option must be given. All other options are passed to the request handler’s constructor.

Raises:

  • AppInitError: The Ruby on Rails application raised an exception or called exit() during startup.

  • SystemCallError, IOError, SocketError: Something went wrong.



80
81
82
83
84
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
# File 'lib/phusion_passenger/classic_rails/application_spawner.rb', line 80

def self.spawn_application(options)
	options = sanitize_spawn_options(options)
	
	a, b = UNIXSocket.pair
	pid = safe_fork('application', true) do
		a.close
		
		file_descriptors_to_leave_open = [0, 1, 2, b.fileno]
		NativeSupport.close_all_file_descriptors(file_descriptors_to_leave_open)
		close_all_io_objects_for_fds(file_descriptors_to_leave_open)
		
		channel = MessageChannel.new(b)
		success = report_app_init_status(channel) do
			prepare_app_process('config/environment.rb', options)
			require File.expand_path('config/environment')
			require 'dispatcher'
			after_loading_app_code(options)
		end
		if success
			start_request_handler(channel, false, options)
		end
	end
	b.close
	Process.waitpid(pid) rescue nil
	
	channel = MessageChannel.new(a)
	unmarshal_and_raise_errors(channel, options["print_exceptions"])
	
	# No exception was raised, so spawning succeeded.
	return AppProcess.read_from_channel(channel)
end

Instance Method Details

#spawn_application(options = {}) ⇒ Object

Spawns an instance of the Rails application. When successful, an AppProcess object will be returned, which represents the spawned Rails application.

options will be passed to the request handler’s constructor.

Raises:

  • AbstractServer::ServerNotStarted: The ApplicationSpawner server hasn’t already been started.

  • ApplicationSpawner::Error: The ApplicationSpawner server exited unexpectedly.



133
134
135
136
137
138
139
140
# File 'lib/phusion_passenger/classic_rails/application_spawner.rb', line 133

def spawn_application(options = {})
	connect do |channel|
		channel.write("spawn_application", *options.to_a.flatten)
		return AppProcess.read_from_channel(channel)
	end
rescue SystemCallError, IOError, SocketError => e
	raise Error, "The application spawner server exited unexpectedly: #{e}"
end

#startObject

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.



148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/phusion_passenger/classic_rails/application_spawner.rb', line 148

def start
	super
	begin
		channel = MessageChannel.new(@owner_socket)
		unmarshal_and_raise_errors(channel, @options["print_exceptions"])
	rescue IOError, SystemCallError, SocketError => e
		stop if started?
		raise Error, "The application spawner server exited unexpectedly: #{e}"
	rescue
		stop if started?
		raise
	end
end