class PhusionPassenger::NativeSupportLoader
Public Class Methods
supported?()
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 27 def self.supported? return !defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby" || RUBY_ENGINE == "rbx" end
Public Instance Methods
start()
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 43 def start try_load || download_binary_and_load || compile_and_load end
try_load()
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 31 def try_load if defined?(NativeSupport) return true else require 'phusion_passenger' load_from_native_support_output_dir || load_from_source_root || load_from_load_path || load_from_home_dir end end
Private Instance Methods
archdir()
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 48 def archdir @archdir ||= begin require 'phusion_passenger/platform_info/binary_compatibility' PlatformInfo.ruby_extension_binary_compatibility_id end end
compile(target_dirs)
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 269 def compile(target_dirs) try_directories(target_dirs) do |target_dir| result = sh_nonfatal("#{PlatformInfo.ruby_command} '#{extconf_rb}'") && sh_nonfatal("make") if result STDERR.puts "Compilation succesful." STDERR.puts "-------------------------------" [target_dir, false] else STDERR.puts "Compilation failed." STDERR.puts "-------------------------------" [nil, false] end end end
compile_and_load()
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 187 def compile_and_load if ENV['PASSENGER_COMPILE_NATIVE_SUPPORT_BINARY'] == '0' STDERR.puts "*** Phusion Passenger: PASSENGER_COMPILE_NATIVE_SUPPORT_BINARY set, " + "not compiling native_support" return false end STDERR.puts "*** Phusion Passenger: no #{library_name} found for " + "the current Ruby interpreter. Compiling one (set " + "PASSENGER_COMPILE_NATIVE_SUPPORT_BINARY=0 to disable)..." require 'fileutils' require 'phusion_passenger/platform_info/ruby' target_dir = compile(installation_target_dirs) if target_dir require "#{target_dir}/#{library_name}" else STDERR.puts "Ruby native_support extension not loaded. Continuing without native_support." return false end end
download(name, output_dir)
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 222 def download(name, output_dir) url = "#{PhusionPassenger::BINARIES_URL_ROOT}/#{PhusionPassenger::VERSION_STRING}/#{name}" filename = "#{output_dir}/#{name}" cache_dir = PhusionPassenger.download_cache_dir if File.exist?("#{cache_dir}/#{name}") FileUtils.cp("#{cache_dir}/#{name}", filename, :verbose => true) return true end STDERR.puts "Attempting to download #{url} into #{output_dir}" cert = PhusionPassenger.binaries_ca_cert_path File.unlink("#{filename}.tmp") rescue nil if PhusionPassenger::PlatformInfo.find_command("wget") result = system("wget", "--tries=3", "-O", "#{filename}.tmp", "--ca-certificate=#{cert}", url) else result = system("curl", url, "-f", "-L", "-o", "#{filename}.tmp", "--cacert", cert) end if result File.rename("#{filename}.tmp", filename) else File.unlink("#{filename}.tmp") rescue nil end return result end
download_binary_and_load()
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 131 def download_binary_and_load if !PhusionPassenger.installed_from_release_package? return end if ENV['PASSENGER_DOWNLOAD_NATIVE_SUPPORT_BINARY'] == '0' STDERR.puts "*** Phusion Passenger: PASSENGER_DOWNLOAD_NATIVE_SUPPORT_BINARY set, " + "not downloading precompiled binary" return end STDERR.puts "*** Phusion Passenger: no #{library_name} found for " + "the current Ruby interpreter. Downloading precompiled binary from the Phusion server " + "(set PASSENGER_DOWNLOAD_NATIVE_SUPPORT_BINARY=0 to disable)..." require 'phusion_passenger/platform_info/ruby' require 'phusion_passenger/utils/tmpio' PhusionPassenger::Utils.mktmpdir("passenger-native-support-") do |dir| Dir.chdir(dir) do basename = "rubyext-#{archdir}.tar.gz" if !download(basename, dir) return false end sh "tar", "xzf", basename sh "rm", "-f", basename STDERR.puts "Checking whether downloaded binary is usable..." File.open("test.rb", "w") do |f| f.puts(%Q{ require File.expand_path('passenger_native_support') f = File.open("test.txt", "w") PhusionPassenger::NativeSupport.writev(f.fileno, ["hello", "\n"]) }) end if sh_nonfatal("#{PlatformInfo.ruby_command} -I. test.rb") && File.exist?("test.txt") && File.read("test.txt") == "hello\n" STDERR.puts "Binary is usable." File.unlink("test.rb") File.unlink("test.txt") result = try_directories(installation_target_dirs) do |target_dir| files = Dir["#{dir}/*"] STDERR.puts "# Installing " + files.map{ |n| File.basename(n) }.join(' ') FileUtils.cp(files, target_dir) require "#{target_dir}/#{library_name}" [true, false] end return result else STDERR.puts "Binary is not usable." return false end end end end
extconf_rb()
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 73 def extconf_rb File.join(PhusionPassenger.ruby_extension_source_dir, "extconf.rb") end
home()
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 62 def home @home ||= begin require 'etc' if !defined?(Etc) home = Etc.getpwuid(Process.uid).dir end end
installation_target_dirs()
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 210 def installation_target_dirs target_dirs = [] if (output_dir = ENV['PASSENGER_NATIVE_SUPPORT_OUTPUT_DIR']) && !output_dir.empty? target_dirs << "#{output_dir}/#{VERSION_STRING}/#{archdir}" end if native_support_dir_in_source_root target_dirs << "#{native_support_dir_in_source_root}/#{archdir}" end target_dirs << "#{home}/#{USER_NAMESPACE_DIRNAME}/native_support/#{VERSION_STRING}/#{archdir}" return target_dirs end
libext()
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 55 def libext @libext ||= begin require 'phusion_passenger/platform_info/operating_system' PlatformInfo.library_extension end end
library_name()
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 69 def library_name return "passenger_native_support.#{libext}" end
load_from_home_dir()
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 122 def load_from_home_dir begin require "#{home}/#{USER_NAMESPACE_DIRNAME}/native_support/#{VERSION_STRING}/#{archdir}/#{library_name}" return true rescue LoadError return false end end
load_from_load_path()
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 115 def load_from_load_path require "/usr/lib64/gems/ruby/passenger-4.0.18/lib/native/#{library_name}" return true rescue LoadError return false end
load_from_native_support_output_dir()
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 86 def load_from_native_support_output_dir # Quick workaround for people suffering from # https://code.google.com/p/phusion-passenger/issues/detail?id=865 output_dir = ENV['PASSENGER_NATIVE_SUPPORT_OUTPUT_DIR'] if output_dir && !output_dir.empty? begin require "#{output_dir}/#{VERSION_STRING}/#{archdir}/#{library_name}" return true rescue LoadError return false end else return false end end
load_from_source_root()
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 102 def load_from_source_root if PhusionPassenger.originally_packaged? begin require "#{native_support_dir_in_source_root}/#{archdir}/#{library_name}" return true rescue LoadError return false end else return false end end
mkdir(dir)
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 248 def mkdir(dir) begin STDERR.puts "# mkdir -p #{dir}" FileUtils.mkdir_p(dir) rescue Errno::EEXIST end end
native_support_dir_in_source_root()
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 77 def native_support_dir_in_source_root if PhusionPassenger.originally_packaged? @native_support_dir_in_source_root ||= File.expand_path("#{PhusionPassenger.source_root}/buildout/ruby") else return nil end end
sh(*args)
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 256 def sh(*args) if !sh_nonfatal(*args) command_string = args.join(' ') raise "Could not compile #{library_name} (\"#{command_string}\" failed)" end end
sh_nonfatal(*args)
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 263 def sh_nonfatal(*args) command_string = args.join(' ') STDERR.puts "# #{command_string}" return system(*args) end
try_directories(dirs) { |dir| ... }
click to toggle source
# File lib/phusion_passenger/native_support.rb, line 286 def try_directories(dirs) result = nil dirs.each_with_index do |dir, i| begin mkdir(dir) File.open("#{dir}/.permission_test", "w").close File.unlink("#{dir}/.permission_test") STDERR.puts "# cd #{dir}" Dir.chdir(dir) do result, should_retry = yield(dir) return result if !should_retry end rescue Errno::EACCES # If we encountered a permission error, then try # the next target directory. If we get a permission # error on the last one too then propagate the # exception. if i == dirs.size - 1 STDERR.puts "Encountered permission error, " + "but no more directories to try. Giving up." STDERR.puts "-------------------------------" return nil else STDERR.puts "Encountered permission error, " + "trying a different directory..." STDERR.puts "-------------------------------" end rescue Errno::ENOTDIR # This can occur when PhusionPassenger.source_root # is a location configuration file, and natively_packaged # is set to false. For example, when we're running # in Phusion Passenger Standalone. In this case # just ignore this directory. if i == dirs.size - 1 STDERR.puts "Not a valid directory, " + "but no more directories to try. Giving up." STDERR.puts "-------------------------------" return nil else STDERR.puts "Not a valid directory. Trying a different one..." STDERR.puts "-------------------------------" end end end end