class PhusionPassenger::WSGI::ApplicationSpawner

Class for spawning WSGI applications.

Constants

REQUEST_HANDLER

Public Class Methods

spawn_application(*args) click to toggle source
# File lib/phusion_passenger/wsgi/application_spawner.rb, line 40
def self.spawn_application(*args)
        @@instance ||= ApplicationSpawner.new
        @@instance.spawn_application(*args)
end

Public Instance Methods

spawn_application(options) click to toggle source

Spawn an instance of the given WSGI application. When successful, an Application object will be returned, which represents the spawned application.

Raises:

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

  • SystemCallError, IOError, SocketError: Something went wrong.

# File lib/phusion_passenger/wsgi/application_spawner.rb, line 53
def spawn_application(options)
        a, b = UNIXSocket.pair
        pid = safe_fork(self.class.to_s, 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)
                
                run(MessageChannel.new(b), options)
        end
        b.close
        Process.waitpid(pid) rescue nil
        
        channel = MessageChannel.new(a)
        return AppProcess.read_from_channel(channel)
end

Private Instance Methods

run(channel, options) click to toggle source
# File lib/phusion_passenger/wsgi/application_spawner.rb, line 72
def run(channel, options)
        $0 = "WSGI: #{options['app_group_name']}"
        prepare_app_process("passenger_wsgi.py", options)
        ENV['WSGI_ENV'] = options['environment']
        
        if defined?(NativeSupport)
                unix_path_max = NativeSupport::UNIX_PATH_MAX
        else
                unix_path_max = 100
        end
        
        socket_file = "#{passenger_tmpdir}/backends/wsgi.#{Process.pid}.#{rand 10000000}"
        socket_file = socket_file.slice(0, unix_path_max - 1)
        server = UNIXServer.new(socket_file)
        begin
                File.chmod(0666, socket_file)
                reader, writer = IO.pipe
                app_process = AppProcess.new(options["app_root"], Process.pid, writer,
                        :main => [socket_file, 'unix'])
                app_process.write_to_channel(channel)
                writer.close
                channel.close
                
                NativeSupport.close_all_file_descriptors([0, 1, 2, server.fileno,
                        reader.fileno])
                exec(REQUEST_HANDLER, socket_file, server.fileno.to_s,
                        reader.fileno.to_s)
        rescue
                server.close
                File.unlink(socket_file)
                raise
        end
end