Class: PhusionPassenger::AppProcess

Class PhusionPassenger::AppProcess |
In: | lib/phusion_passenger/app_process.rb
Parent: | Object

Contains various information about an application process.

Methods

- close
- detect_framework_version
- new
- read_from_channel
- write_to_channel

Attributes

[R] | app_root | The root directory of this application process.
[R] | owner_pipe | The owner pipe of the application instance (an IO object). Please see RequestHandler for a description of the owner pipe.
[R] | pid | This process‘s PID.
[R] | server_sockets | A hash containing all server sockets that this application process listens on. The hash is in the form of:
      {
         name1 => [socket_address1, socket_type1],
         name2 => [socket_address2, socket_type2],
         ...
      }
`name` is a Symbol. `socket_addressx` is the address of the socket and +socket_type1+ is the socket‘s type (either ‘unix’ or ‘tcp’). There‘s guaranteed to be at least one server socket, namely one with the name +:main+.

Public Class methods
detect_framework_version(app_root)

- Returns the Ruby on Rails version that the application requires.
- Returns `:vendor` if the application has a vendored Rails.
- Returns nil if the application doesn‘t specify a particular version.

Raises VersionNotFound if the required Rails version is not installed.

[ show source ]

        # File lib/phusion_passenger/app_process.rb, line 59
    59:         def self.detect_framework_version(app_root)
    60:                 if File.directory?("#{app_root}/vendor/rails/railties")
    61:                         # NOTE: We must check for 'rails/railties' and not just 'rails'.
    62:                         # Typo's vendor directory contains an empty 'rails' directory.
    63:                         return :vendor
    64:                 end
    65:
    66:                 environment_rb = File.read("#{app_root}/config/environment.rb")
    67:                 environment_rb =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
    68:                 gem_version_spec = $1
    69:                 if gem_version_spec.nil?
    70:                         return nil
    71:                 end
    72:
    73:                 search_results = Gem.cache.search(Gem::Dependency.new('rails', gem_version_spec), true)
    74:                 found_version = search_results.map do |x|
    75:                         x.version.version
    76:                 end.sort.last
    77:                 if found_version.nil?
    78:                         # If this error was reported before, then the cache might be out of
    79:                         # date because the Rails version may have been installed now.
    80:                         # So we reload the RubyGems cache and try again.
    81:                         Gem.clear_paths
    82:                         search_results = Gem.cache.search(Gem::Dependency.new('rails', gem_version_spec), true)
    83:                         found_version = search_results.map do |x|
    84:                                 x.version.version
    85:                         end.sort.last
    86:                 end
    87:
    88:                 if found_version.nil?
    89:                         raise VersionNotFound.new("There is no Ruby on Rails version " <<
    90:                                 "installed that matches version \"#{gem_version_spec}\"",
    91:                                 gem_version_spec)
    92:                 else
    93:                         return found_version
    94:                 end
    95:         end

new(app_root, pid, owner_pipe, server_sockets)

Creates a new AppProcess instance. The parameters correspond with the attributes of the same names. No exceptions will be thrown.

[ show source ]

         # File lib/phusion_passenger/app_process.rb, line 137
    137:         def initialize(app_root, pid, owner_pipe, server_sockets)
    138:                 @app_root   = app_root
    139:                 @pid        = pid
    140:                 @owner_pipe = owner_pipe
    141:
    142:                 # We copy the values like this so one can directly pass
    143:                 # AbstractRequestHandler#server_sockets as arguments
    144:                 # without having AppProcess store references to the socket
    145:                 # IO objects.
    146:                 @server_sockets = {}
    147:                 server_sockets.each_pair do |name, value|
    148:                         @server_sockets[name] = [value[0], value[1]]
    149:                 end
    150:         end

read_from_channel(channel)

Construct an AppProcess by reading information from the given MessageChannel. The other side of the channel must be writing AppProcess information using AppProcess#write_to_channel.

Might raise SystemCallError, IOError or SocketError.

[ show source ]

         # File lib/phusion_passenger/app_process.rb, line 102
    102:         def self.read_from_channel(channel)
    103:                 app_root, pid, n_server_sockets = channel.read
    104:                 if app_root.nil?
    105:                         raise IOError, "Connection closed"
    106:                 end
    107:
    108:                 server_sockets = {}
    109:                 n_server_sockets.to_i.times do
    110:                         message = channel.read
    111:                         if message.nil?
    112:                                 raise IOError, "Connection closed"
    113:                         end
    114:                         name = message.shift
    115:                         server_sockets[name.to_sym] = message
    116:                 end
    117:
    118:                 owner_pipe = channel.recv_io
    119:
    120:                 return new(app_root, pid.to_i, owner_pipe, server_sockets)
    121:         end

Public Instance methods
close()

Close the connection with the application process. If there are no other processes that have connections to this application process, then it will shutdown as soon as possible.

See also AbstractRequestHandler#owner_pipe.

[ show source ]

         # File lib/phusion_passenger/app_process.rb, line 157
    157:         def close
    158:                 @owner_pipe.close rescue nil
    159:         end

write_to_channel(channel)

Write this AppProcess‘s information over the given MessageChannel. The other side must read the information using AppProces.read_from_channel.

Might raise SystemCallError, IOError or SocketError.

[ show source ]

         # File lib/phusion_passenger/app_process.rb, line 127
    127:         def write_to_channel(channel)
    128:                 channel.write(@app_root, @pid, @server_sockets.size)
    129:                 @server_sockets.each_pair do |name, value|
    130:                         channel.write(name.to_s, *value)
    131:                 end
    132:                 channel.send_io(@owner_pipe)
    133:         end