passenger 5.0.0.beta3 → 5.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (218) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/.editorconfig +11 -5
  5. data/CHANGELOG +38 -0
  6. data/CONTRIBUTING.md +1 -4
  7. data/Gemfile +0 -1
  8. data/Gemfile.lock +0 -2
  9. data/Rakefile +33 -33
  10. data/bin/passenger +1 -1
  11. data/bin/passenger-config +1 -1
  12. data/bin/passenger-install-apache2-module +800 -800
  13. data/bin/passenger-install-nginx-module +592 -592
  14. data/bin/passenger-memory-stats +127 -127
  15. data/bin/passenger-status +216 -216
  16. data/build/agents.rb +127 -127
  17. data/build/apache2.rb +87 -87
  18. data/build/basics.rb +60 -60
  19. data/build/common_library.rb +165 -165
  20. data/build/cplusplus_support.rb +51 -51
  21. data/build/cxx_tests.rb +268 -268
  22. data/build/debian.rb +143 -143
  23. data/build/documentation.rb +58 -58
  24. data/build/integration_tests.rb +81 -81
  25. data/build/misc.rb +132 -132
  26. data/build/nginx.rb +20 -20
  27. data/build/node_tests.rb +7 -7
  28. data/build/oxt_tests.rb +14 -14
  29. data/build/packaging.rb +570 -570
  30. data/build/preprocessor.rb +260 -260
  31. data/build/rake_extensions.rb +71 -71
  32. data/build/ruby_extension.rb +29 -29
  33. data/build/ruby_tests.rb +6 -6
  34. data/build/test_basics.rb +37 -37
  35. data/debian.template/control.template +3 -5
  36. data/dev/copy_boost_headers +134 -134
  37. data/dev/install_scripts_bootstrap_code.rb +25 -25
  38. data/dev/list_tests +20 -20
  39. data/dev/ruby_server.rb +223 -223
  40. data/dev/runner +18 -18
  41. data/doc/ServerOptimizationGuide.txt.md +55 -2
  42. data/doc/Users guide Nginx.txt +0 -26
  43. data/doc/Users guide Standalone.txt +5 -1
  44. data/doc/users_guide_snippets/tips.txt +9 -0
  45. data/ext/common/ApplicationPool2/Group.h +23 -11
  46. data/ext/common/ApplicationPool2/Implementation.cpp +32 -7
  47. data/ext/common/ApplicationPool2/Pool.h +22 -17
  48. data/ext/common/ApplicationPool2/SmartSpawner.h +4 -1
  49. data/ext/common/ApplicationPool2/Spawner.h +1 -1
  50. data/ext/common/Constants.h +1 -1
  51. data/ext/common/agents/Base.cpp +35 -20
  52. data/ext/common/agents/HelperAgent/Main.cpp +8 -1
  53. data/ext/common/agents/HelperAgent/OptionParser.h +18 -4
  54. data/ext/common/agents/HelperAgent/RequestHandler.h +2 -83
  55. data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +54 -1
  56. data/ext/common/agents/HelperAgent/RequestHandler/InitRequest.cpp +7 -4
  57. data/ext/common/agents/Main.cpp +1 -1
  58. data/ext/common/agents/Watchdog/Main.cpp +54 -19
  59. data/ext/nginx/Configuration.c +7 -0
  60. data/ext/nginx/ContentHandler.c +9 -1
  61. data/helper-scripts/backtrace-sanitizer.rb +106 -87
  62. data/helper-scripts/crash-watch.rb +32 -0
  63. data/helper-scripts/download_binaries/extconf.rb +38 -38
  64. data/helper-scripts/meteor-loader.rb +107 -107
  65. data/helper-scripts/prespawn +101 -101
  66. data/helper-scripts/rack-loader.rb +96 -96
  67. data/helper-scripts/rack-preloader.rb +137 -137
  68. data/lib/phusion_passenger.rb +292 -292
  69. data/lib/phusion_passenger/abstract_installer.rb +438 -438
  70. data/lib/phusion_passenger/active_support3_extensions/init.rb +168 -170
  71. data/lib/phusion_passenger/admin_tools.rb +20 -20
  72. data/lib/phusion_passenger/admin_tools/instance.rb +178 -178
  73. data/lib/phusion_passenger/admin_tools/instance_registry.rb +61 -61
  74. data/lib/phusion_passenger/admin_tools/memory_stats.rb +267 -267
  75. data/lib/phusion_passenger/apache2/config_options.rb +182 -182
  76. data/lib/phusion_passenger/common_library.rb +479 -485
  77. data/lib/phusion_passenger/config/about_command.rb +161 -161
  78. data/lib/phusion_passenger/config/admin_command_command.rb +129 -129
  79. data/lib/phusion_passenger/config/agent_compiler.rb +121 -121
  80. data/lib/phusion_passenger/config/build_native_support_command.rb +43 -43
  81. data/lib/phusion_passenger/config/command.rb +25 -25
  82. data/lib/phusion_passenger/config/compile_agent_command.rb +62 -62
  83. data/lib/phusion_passenger/config/compile_nginx_engine_command.rb +88 -73
  84. data/lib/phusion_passenger/config/detach_process_command.rb +72 -72
  85. data/lib/phusion_passenger/config/download_agent_command.rb +246 -227
  86. data/lib/phusion_passenger/config/download_nginx_engine_command.rb +245 -224
  87. data/lib/phusion_passenger/config/install_agent_command.rb +144 -132
  88. data/lib/phusion_passenger/config/install_standalone_runtime_command.rb +205 -185
  89. data/lib/phusion_passenger/config/installation_utils.rb +204 -204
  90. data/lib/phusion_passenger/config/list_instances_command.rb +64 -64
  91. data/lib/phusion_passenger/config/main.rb +152 -152
  92. data/lib/phusion_passenger/config/nginx_engine_compiler.rb +319 -300
  93. data/lib/phusion_passenger/config/reopen_logs_command.rb +67 -67
  94. data/lib/phusion_passenger/config/restart_app_command.rb +155 -155
  95. data/lib/phusion_passenger/config/system_metrics_command.rb +13 -13
  96. data/lib/phusion_passenger/config/utils.rb +95 -95
  97. data/lib/phusion_passenger/config/validate_install_command.rb +198 -198
  98. data/lib/phusion_passenger/console_text_template.rb +25 -25
  99. data/lib/phusion_passenger/constants.rb +90 -90
  100. data/lib/phusion_passenger/debug_logging.rb +106 -106
  101. data/lib/phusion_passenger/loader_shared_helpers.rb +447 -432
  102. data/lib/phusion_passenger/message_channel.rb +312 -312
  103. data/lib/phusion_passenger/message_client.rb +176 -176
  104. data/lib/phusion_passenger/native_support.rb +369 -369
  105. data/lib/phusion_passenger/nginx/config_options.rb +297 -297
  106. data/lib/phusion_passenger/packaging.rb +131 -131
  107. data/lib/phusion_passenger/platform_info.rb +360 -360
  108. data/lib/phusion_passenger/platform_info/apache.rb +767 -767
  109. data/lib/phusion_passenger/platform_info/apache_detector.rb +199 -199
  110. data/lib/phusion_passenger/platform_info/binary_compatibility.rb +107 -107
  111. data/lib/phusion_passenger/platform_info/compiler.rb +570 -570
  112. data/lib/phusion_passenger/platform_info/curl.rb +32 -32
  113. data/lib/phusion_passenger/platform_info/cxx_portability.rb +188 -188
  114. data/lib/phusion_passenger/platform_info/depcheck.rb +372 -372
  115. data/lib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +109 -109
  116. data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +4 -4
  117. data/lib/phusion_passenger/platform_info/depcheck_specs/gems.rb +10 -34
  118. data/lib/phusion_passenger/platform_info/depcheck_specs/libs.rb +101 -101
  119. data/lib/phusion_passenger/platform_info/depcheck_specs/ruby.rb +5 -5
  120. data/lib/phusion_passenger/platform_info/depcheck_specs/utilities.rb +13 -13
  121. data/lib/phusion_passenger/platform_info/linux.rb +55 -55
  122. data/lib/phusion_passenger/platform_info/operating_system.rb +149 -149
  123. data/lib/phusion_passenger/platform_info/ruby.rb +468 -448
  124. data/lib/phusion_passenger/platform_info/zlib.rb +9 -9
  125. data/lib/phusion_passenger/plugin.rb +66 -66
  126. data/lib/phusion_passenger/preloader_shared_helpers.rb +126 -126
  127. data/lib/phusion_passenger/public_api.rb +191 -191
  128. data/lib/phusion_passenger/rack/out_of_band_gc.rb +93 -94
  129. data/lib/phusion_passenger/rack/thread_handler_extension.rb +231 -227
  130. data/lib/phusion_passenger/request_handler.rb +567 -577
  131. data/lib/phusion_passenger/request_handler/thread_handler.rb +379 -381
  132. data/lib/phusion_passenger/ruby_core_enhancements.rb +86 -86
  133. data/lib/phusion_passenger/ruby_core_io_enhancements.rb +74 -74
  134. data/lib/phusion_passenger/simple_benchmarking.rb +25 -25
  135. data/lib/phusion_passenger/standalone/app_finder.rb +153 -150
  136. data/lib/phusion_passenger/standalone/command.rb +44 -40
  137. data/lib/phusion_passenger/standalone/config_utils.rb +53 -53
  138. data/lib/phusion_passenger/standalone/control_utils.rb +38 -59
  139. data/lib/phusion_passenger/standalone/main.rb +73 -73
  140. data/lib/phusion_passenger/standalone/start_command.rb +697 -685
  141. data/lib/phusion_passenger/standalone/start_command/builtin_engine.rb +193 -155
  142. data/lib/phusion_passenger/standalone/start_command/nginx_engine.rb +162 -133
  143. data/lib/phusion_passenger/standalone/status_command.rb +64 -64
  144. data/lib/phusion_passenger/standalone/stop_command.rb +72 -72
  145. data/lib/phusion_passenger/standalone/version_command.rb +9 -9
  146. data/lib/phusion_passenger/union_station/connection.rb +32 -32
  147. data/lib/phusion_passenger/union_station/core.rb +251 -251
  148. data/lib/phusion_passenger/union_station/transaction.rb +126 -126
  149. data/lib/phusion_passenger/utils.rb +199 -167
  150. data/lib/phusion_passenger/utils/ansi_colors.rb +128 -128
  151. data/lib/phusion_passenger/utils/download.rb +196 -196
  152. data/lib/phusion_passenger/utils/file_system_watcher.rb +158 -158
  153. data/lib/phusion_passenger/utils/hosts_file_parser.rb +101 -101
  154. data/lib/phusion_passenger/utils/lock.rb +31 -31
  155. data/lib/phusion_passenger/utils/native_support_utils.rb +31 -31
  156. data/lib/phusion_passenger/utils/progress_bar.rb +26 -26
  157. data/lib/phusion_passenger/utils/shellwords.rb +20 -20
  158. data/lib/phusion_passenger/utils/terminal_choice_menu.rb +206 -206
  159. data/lib/phusion_passenger/utils/unseekable_socket.rb +272 -272
  160. data/lib/phusion_passenger/vendor/crash_watch/app.rb +129 -0
  161. data/lib/phusion_passenger/vendor/crash_watch/gdb_controller.rb +341 -0
  162. data/lib/phusion_passenger/vendor/crash_watch/version.rb +24 -0
  163. data/lib/phusion_passenger/vendor/daemon_controller.rb +877 -0
  164. data/lib/phusion_passenger/vendor/daemon_controller/lock_file.rb +127 -0
  165. data/lib/phusion_passenger/vendor/daemon_controller/spawn.rb +26 -0
  166. data/lib/phusion_passenger/vendor/daemon_controller/version.rb +29 -0
  167. data/packaging/rpm/passenger_spec/passenger.spec.template +0 -1
  168. data/passenger.gemspec +0 -1
  169. data/resources/templates/config/nginx_engine_compiler/possible_solutions_for_download_and_extraction_problems.txt.erb +27 -0
  170. data/resources/templates/standalone/config.erb +19 -15
  171. data/test/integration_tests/apache2_tests.rb +566 -566
  172. data/test/integration_tests/downloaded_binaries_tests.rb +126 -125
  173. data/test/integration_tests/native_packaging_spec.rb +296 -296
  174. data/test/integration_tests/nginx_tests.rb +393 -393
  175. data/test/integration_tests/shared/example_webapp_tests.rb +282 -280
  176. data/test/integration_tests/source_packaging_test.rb +138 -138
  177. data/test/integration_tests/spec_helper.rb +5 -5
  178. data/test/integration_tests/standalone_tests.rb +367 -367
  179. data/test/ruby/debug_logging_spec.rb +133 -133
  180. data/test/ruby/message_channel_spec.rb +186 -186
  181. data/test/ruby/rack/loader_spec.rb +28 -28
  182. data/test/ruby/rack/preloader_spec.rb +34 -34
  183. data/test/ruby/rails3.0/loader_spec.rb +12 -12
  184. data/test/ruby/rails3.0/preloader_spec.rb +18 -18
  185. data/test/ruby/rails3.1/loader_spec.rb +12 -12
  186. data/test/ruby/rails3.1/preloader_spec.rb +18 -18
  187. data/test/ruby/rails3.2/loader_spec.rb +12 -12
  188. data/test/ruby/rails3.2/preloader_spec.rb +18 -18
  189. data/test/ruby/rails4.0/loader_spec.rb +12 -12
  190. data/test/ruby/rails4.0/preloader_spec.rb +18 -18
  191. data/test/ruby/rails4.1/loader_spec.rb +12 -12
  192. data/test/ruby/rails4.1/preloader_spec.rb +18 -18
  193. data/test/ruby/request_handler_spec.rb +730 -730
  194. data/test/ruby/shared/loader_sharedspec.rb +224 -224
  195. data/test/ruby/shared/rails/union_station_extensions_sharedspec.rb +327 -327
  196. data/test/ruby/shared/ruby_loader_sharedspec.rb +47 -47
  197. data/test/ruby/spec_helper.rb +65 -65
  198. data/test/ruby/standalone/runtime_installer_spec.rb +384 -384
  199. data/test/ruby/union_station_spec.rb +276 -276
  200. data/test/ruby/utils/file_system_watcher_spec.rb +220 -220
  201. data/test/ruby/utils/hosts_file_parser.rb +248 -248
  202. data/test/ruby/utils/tee_input_spec.rb +215 -215
  203. data/test/ruby/utils/unseekable_socket_spec.rb +57 -57
  204. data/test/ruby/utils_spec.rb +21 -21
  205. data/test/stub/rack/config.ru +87 -87
  206. data/test/stub/rack/library.rb +8 -8
  207. data/test/stub/rack/start.rb +30 -30
  208. data/test/support/apache2_controller.rb +191 -191
  209. data/test/support/nginx_controller.rb +90 -99
  210. data/test/support/placebo-preloader.rb +57 -57
  211. data/test/support/test_helper.rb +435 -435
  212. metadata +11 -21
  213. metadata.gz.asc +7 -7
  214. data/lib/phusion_passenger/standalone/command2.rb +0 -292
  215. data/lib/phusion_passenger/standalone/start2_command.rb +0 -799
  216. data/resources/templates/standalone/download_tool_missing.txt.erb +0 -18
  217. data/resources/templates/standalone/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -17
  218. data/resources/templates/standalone/run_installer_as_root.txt.erb +0 -8
@@ -1,106 +1,97 @@
1
1
  require 'erb'
2
- begin
3
- require 'daemon_controller'
4
- rescue LoadError
5
- STDERR.puts "*** ERROR: daemon_controller is not installed. Please install with: "
6
- STDERR.puts
7
- STDERR.puts " gem install daemon_controller"
8
- STDERR.puts
9
- exit!(1)
10
- end
11
-
2
+ PhusionPassenger.require_passenger_lib 'vendor/daemon_controller'
12
3
  PhusionPassenger.require_passenger_lib 'platform_info/ruby'
13
4
 
14
5
  class NginxController
15
- PlatformInfo = PhusionPassenger::PlatformInfo
16
- TEMPLATE_DIR = File.expand_path(File.dirname(__FILE__) + "/../stub/nginx")
17
- PORT = 64507
18
-
19
- def initialize(root_dir)
20
- root_dir = File.expand_path(root_dir)
21
- @passenger_root = PhusionPassenger.install_spec
22
- @nginx_root = root_dir
23
- @port = PORT
24
- @config_file = "#{root_dir}/nginx.conf"
25
- @pid_file = "#{root_dir}/nginx.pid"
26
- @log_file = "#{root_dir}/error.log"
27
- @controller = DaemonController.new(
28
- :identifier => 'Nginx',
29
- :start_command => "#{CONFIG['nginx']} -c '#{@config_file}'",
30
- :ping_command => [:tcp, '127.0.0.1', PORT],
31
- :pid_file => @pid_file,
32
- :log_file => @log_file,
33
- :timeout => 25,
34
- :before_start => method(:write_nginx_config_files)
35
- )
36
-
37
- @servers = []
38
- @max_pool_size = 1
39
- end
40
-
41
- def set(options)
42
- options.each_pair do |key, value|
43
- instance_variable_set("@#{key}", value)
44
- end
45
- end
46
-
47
- def start
48
- stop
49
- @controller.start
50
- end
51
-
52
- def stop
53
- @controller.stop
54
- # On OS X, the Nginx server socket may linger around for a while
55
- # after Nginx shutdown, despite Nginx setting SO_REUSEADDR.
56
- sockaddr = Socket.pack_sockaddr_in(PORT, '127.0.0.1')
57
- eventually(30) do
58
- !@controller.send(:ping_socket, Socket::Constants::AF_INET, sockaddr)
59
- end
60
- end
61
-
62
- def running?
63
- return @controller.running?
64
- end
65
-
66
- def port
67
- return @port
68
- end
69
-
70
- def add_server
71
- server = Server.new
72
- yield server
73
- @servers << server
74
- end
6
+ PlatformInfo = PhusionPassenger::PlatformInfo
7
+ TEMPLATE_DIR = File.expand_path(File.dirname(__FILE__) + "/../stub/nginx")
8
+ PORT = 64507
9
+
10
+ def initialize(root_dir)
11
+ root_dir = File.expand_path(root_dir)
12
+ @passenger_root = PhusionPassenger.install_spec
13
+ @nginx_root = root_dir
14
+ @port = PORT
15
+ @config_file = "#{root_dir}/nginx.conf"
16
+ @pid_file = "#{root_dir}/nginx.pid"
17
+ @log_file = "#{root_dir}/error.log"
18
+ @controller = PhusionPassenger::DaemonController.new(
19
+ :identifier => 'Nginx',
20
+ :start_command => "#{CONFIG['nginx']} -c '#{@config_file}'",
21
+ :ping_command => [:tcp, '127.0.0.1', PORT],
22
+ :pid_file => @pid_file,
23
+ :log_file => @log_file,
24
+ :timeout => 25,
25
+ :before_start => method(:write_nginx_config_files)
26
+ )
27
+
28
+ @servers = []
29
+ @max_pool_size = 1
30
+ end
31
+
32
+ def set(options)
33
+ options.each_pair do |key, value|
34
+ instance_variable_set("@#{key}", value)
35
+ end
36
+ end
37
+
38
+ def start
39
+ stop
40
+ @controller.start
41
+ end
42
+
43
+ def stop
44
+ @controller.stop
45
+ # On OS X, the Nginx server socket may linger around for a while
46
+ # after Nginx shutdown, despite Nginx setting SO_REUSEADDR.
47
+ sockaddr = Socket.pack_sockaddr_in(PORT, '127.0.0.1')
48
+ eventually(30) do
49
+ !@controller.send(:ping_socket, Socket::Constants::AF_INET, sockaddr)
50
+ end
51
+ end
52
+
53
+ def running?
54
+ return @controller.running?
55
+ end
56
+
57
+ def port
58
+ return @port
59
+ end
60
+
61
+ def add_server
62
+ server = Server.new
63
+ yield server
64
+ @servers << server
65
+ end
75
66
 
76
67
  private
77
- class Server
78
- attr_accessor :values
79
- attr_accessor :extra
80
-
81
- def initialize
82
- @values = { :passenger_enabled => "on" }
83
- end
84
-
85
- def [](key)
86
- return @values[key]
87
- end
88
-
89
- def []=(key, value)
90
- @values[key] = value
91
- end
92
-
93
- def <<(text)
94
- @extra = text
95
- end
96
- end
97
-
98
- def write_nginx_config_files
99
- template = ERB.new(File.read("#{TEMPLATE_DIR}/nginx.conf.erb"))
100
- File.write(@config_file, template.result(get_binding))
101
- end
102
-
103
- def get_binding
104
- return binding
105
- end
68
+ class Server
69
+ attr_accessor :values
70
+ attr_accessor :extra
71
+
72
+ def initialize
73
+ @values = { :passenger_enabled => "on" }
74
+ end
75
+
76
+ def [](key)
77
+ return @values[key]
78
+ end
79
+
80
+ def []=(key, value)
81
+ @values[key] = value
82
+ end
83
+
84
+ def <<(text)
85
+ @extra = text
86
+ end
87
+ end
88
+
89
+ def write_nginx_config_files
90
+ template = ERB.new(File.read("#{TEMPLATE_DIR}/nginx.conf.erb"))
91
+ File.write(@config_file, template.result(get_binding))
92
+ end
93
+
94
+ def get_binding
95
+ return binding
96
+ end
106
97
  end
@@ -15,8 +15,8 @@ abort "Invalid initialization header" if STDIN.readline != "You have control 1.0
15
15
 
16
16
  options = {}
17
17
  while (line = STDIN.readline) != "\n"
18
- name, value = line.strip.split(/: */, 2)
19
- options[name] = value
18
+ name, value = line.strip.split(/: */, 2)
19
+ options[name] = value
20
20
  end
21
21
 
22
22
  socket_filename = "/tmp/placebo-preloader.sock.#{Process.pid}"
@@ -26,63 +26,63 @@ puts "!> socket: unix:#{socket_filename}"
26
26
  puts "!> "
27
27
 
28
28
  def process_client_command(server, client, command)
29
- if command == "spawn\n"
30
- options = {}
31
- while (line = client.readline) != "\n"
32
- name, value = line.strip.split(/: */, 2)
33
- options[name] = value
34
- end
35
-
36
- command = options["start_command"].split("\t")
37
- process_title = options["process_title"]
38
- process_title = command[0] if !process_title || process_title.empty?
39
- command[0] = [command[0], process_title]
40
-
41
- pid = fork do
42
- begin
43
- STDIN.reopen(client)
44
- STDOUT.reopen(client)
45
- STDOUT.sync = true
46
- server.close
47
- client.close
48
- puts "OK"
49
- puts Process.pid
50
- exec(*command)
51
- rescue Exception => e
52
- STDERR.puts "*** ERROR: #{e}\n#{e.backtrace.join("\n")}"
53
- ensure
54
- STDERR.flush
55
- exit!(1)
56
- end
57
- end
58
- Process.detach(pid)
59
- elsif command == "pid\n"
60
- client.write("#{Process.pid}\n")
61
- else
62
- client.write("unknown request\n")
63
- end
29
+ if command == "spawn\n"
30
+ options = {}
31
+ while (line = client.readline) != "\n"
32
+ name, value = line.strip.split(/: */, 2)
33
+ options[name] = value
34
+ end
35
+
36
+ command = options["start_command"].split("\t")
37
+ process_title = options["process_title"]
38
+ process_title = command[0] if !process_title || process_title.empty?
39
+ command[0] = [command[0], process_title]
40
+
41
+ pid = fork do
42
+ begin
43
+ STDIN.reopen(client)
44
+ STDOUT.reopen(client)
45
+ STDOUT.sync = true
46
+ server.close
47
+ client.close
48
+ puts "OK"
49
+ puts Process.pid
50
+ exec(*command)
51
+ rescue Exception => e
52
+ STDERR.puts "*** ERROR: #{e}\n#{e.backtrace.join("\n")}"
53
+ ensure
54
+ STDERR.flush
55
+ exit!(1)
56
+ end
57
+ end
58
+ Process.detach(pid)
59
+ elsif command == "pid\n"
60
+ client.write("#{Process.pid}\n")
61
+ else
62
+ client.write("unknown request\n")
63
+ end
64
64
  end
65
65
 
66
66
  begin
67
- exit if ARGV[0] == "exit-immediately"
68
- while true
69
- ios = select([server, STDIN])[0]
70
- if ios.include?(server)
71
- client = server.accept
72
- begin
73
- process_client_command(server, client, client.readline)
74
- ensure
75
- client.close
76
- end
77
- end
78
- if ios.include?(STDIN)
79
- begin
80
- STDIN.readline
81
- rescue EOFError
82
- exit
83
- end
84
- end
85
- end
67
+ exit if ARGV[0] == "exit-immediately"
68
+ while true
69
+ ios = select([server, STDIN])[0]
70
+ if ios.include?(server)
71
+ client = server.accept
72
+ begin
73
+ process_client_command(server, client, client.readline)
74
+ ensure
75
+ client.close
76
+ end
77
+ end
78
+ if ios.include?(STDIN)
79
+ begin
80
+ STDIN.readline
81
+ rescue EOFError
82
+ exit
83
+ end
84
+ end
85
+ end
86
86
  ensure
87
- File.unlink(socket_filename) rescue nil
87
+ File.unlink(socket_filename) rescue nil
88
88
  end
@@ -1,10 +1,10 @@
1
1
  # Clean Bundler environment variables. Otherwise we can't test against multiple Rails versions.
2
2
  if defined?(Bundler)
3
- clean_env = nil
4
- Bundler.with_clean_env do
5
- clean_env = ENV.to_hash
6
- end
7
- ENV.replace(clean_env)
3
+ clean_env = nil
4
+ Bundler.with_clean_env do
5
+ clean_env = ENV.to_hash
6
+ end
7
+ ENV.replace(clean_env)
8
8
  end
9
9
 
10
10
  require 'fileutils'
@@ -18,438 +18,438 @@ PhusionPassenger.require_passenger_lib 'platform_info/ruby'
18
18
 
19
19
  # Module containing helper methods, to be included in unit tests.
20
20
  module TestHelper
21
- ######## Stub helpers ########
22
-
23
- class Stub
24
- attr_reader :app_root
25
- attr_reader :full_app_root
26
-
27
- def self.use(name, app_root = nil)
28
- stub = new(name, app_root)
29
- begin
30
- yield stub
31
- ensure
32
- stub.destroy
33
- end
34
- end
35
-
36
- def initialize(name, app_root = nil)
37
- @name = name
38
- if !File.exist?(stub_source_dir)
39
- raise Errno::ENOENT, "Stub '#{name}' not found."
40
- end
41
-
42
- if app_root
43
- @app_root = app_root
44
- else
45
- identifier = name.gsub('/', '-')
46
- @app_root = "tmp.#{identifier}.#{object_id}"
47
- end
48
- @full_app_root = File.expand_path(@app_root)
49
- remove_dir_tree(@full_app_root)
50
- FileUtils.mkdir_p(@full_app_root)
51
- copy_stub_contents
52
- system("chmod", "-R", "a+rw", @full_app_root)
53
- end
54
-
55
- def reset
56
- # Empty directory without removing the directory itself,
57
- # allowing processes with this directory as current working
58
- # directory to continue to function properly.
59
- files = Dir["#{@full_app_root}/*"]
60
- files |= Dir["#{@full_app_root}/.*"]
61
- files.delete("#{@full_app_root}/.")
62
- files.delete("#{@full_app_root}/..")
63
- FileUtils.chmod_R(0777, files)
64
- FileUtils.rm_rf(files)
65
-
66
- copy_stub_contents
67
- system("chmod", "-R", "a+rw", @full_app_root)
68
- end
69
-
70
- def move(new_app_root)
71
- File.rename(@full_app_root, new_app_root)
72
- @app_root = new_app_root
73
- @full_app_root = File.expand_path(new_app_root)
74
- end
75
-
76
- def destroy
77
- remove_dir_tree(@full_app_root)
78
- end
79
-
80
- def full_app_root
81
- return File.expand_path(@app_root)
82
- end
83
-
84
- def public_file(name)
85
- return File.binread("#{@full_app_root}/public/#{name}")
86
- end
87
-
88
- private
89
- def stub_source_dir
90
- return "stub/#{@name}"
91
- end
92
-
93
- def copy_stub_contents
94
- FileUtils.cp_r("#{stub_source_dir}/.", @full_app_root)
95
- end
96
- end
97
-
98
- class RackStub < Stub
99
- def startup_file
100
- return "#{@full_app_root}/config.ru"
101
- end
102
-
103
- private
104
- def copy_stub_contents
105
- super
106
- if PhusionPassenger.build_system_dir
107
- build_system_dir = PhusionPassenger.build_system_dir
108
- if !File.exist?("#{@full_app_root}/Gemfile")
109
- FileUtils.cp("#{build_system_dir}/Gemfile", @full_app_root)
110
- FileUtils.cp("#{build_system_dir}/Gemfile.lock", @full_app_root)
111
- if File.exist?("#{build_system_dir}/.bundle")
112
- FileUtils.cp_r("#{build_system_dir}/.bundle", @full_app_root)
113
- end
114
- end
115
- end
116
- end
117
- end
118
-
119
- class PythonStub < Stub
120
- def startup_file
121
- return "#{@full_app_root}/passenger_wsgi.py"
122
- end
123
- end
124
-
125
- class NodejsStub < Stub
126
- def startup_file
127
- return "#{@full_app_root}/app.js"
128
- end
129
- end
130
-
131
- def describe_rails_versions(matcher, &block)
132
- if ENV['ONLY_RAILS_VERSION'] && !ENV['ONLY_RAILS_VERSION'].empty?
133
- found_versions = [ENV['ONLY_RAILS_VERSION']]
134
- else
135
- found_versions = Dir.entries("stub/rails_apps").grep(/^\d+\.\d+$/)
136
- if RUBY_VERSION >= '1.9.0'
137
- # Only Rails >= 2.3 is compatible with Ruby 1.9.
138
- found_versions.reject! do |version|
139
- version < '2.3'
140
- end
141
- elsif RUBY_VERSION <= '1.8.6'
142
- # Rails >= 3 dropped support for 1.8.6 and older.
143
- found_versions.reject! do |version|
144
- version >= '3.0'
145
- end
146
- end
147
- end
148
-
149
- case matcher
150
- when /^<= (.+)$/
151
- max_version = $1
152
- found_versions.reject! do |version|
153
- version > max_version
154
- end
155
- when /^>= (.+)$/
156
- min_version = $1
157
- found_versions.reject! do |version|
158
- version < min_version
159
- end
160
- when /^= (.+)$/
161
- exact_version = $1
162
- found_versions.reject! do |version|
163
- version != exact_version
164
- end
165
- else
166
- raise ArgumentError, "Unknown matcher string '#{matcher}'"
167
- end
168
-
169
- found_versions.sort.each do |version|
170
- klass = describe("Rails #{version}", &block)
171
- klass.send(:define_method, :rails_version) do
172
- version
173
- end
174
- end
175
- end
176
-
177
-
178
- ######## HTTP helpers ########
179
- # Before using these methods, one must set the '@server' instance variable
180
- # and implement the start_web_server_if_necessary method.
181
-
182
- def get(uri)
183
- if @server.nil?
184
- raise "You must set the '@server' instance variable before get() can be used. For example, @server = 'http://mydomain.test/'"
185
- end
186
- start_web_server_if_necessary
187
- return Net::HTTP.get(URI.parse("#{@server}#{uri}"))
188
- end
189
-
190
- def get_response(uri)
191
- if @server.nil?
192
- raise "You must set the '@server' instance variable before get() can be used. For example, @server = 'http://mydomain.test/'"
193
- end
194
- start_web_server_if_necessary
195
- return Net::HTTP.get_response(URI.parse("#{@server}#{uri}"))
196
- end
197
-
198
- def post(uri, params = {})
199
- if @server.nil?
200
- raise "You must set the '@server' instance variable before get() can be used. For example, @server = 'http://mydomain.test/'"
201
- end
202
- start_web_server_if_necessary
203
- url = URI.parse("#{@server}#{uri}")
204
- if params.values.any? { |x| x.respond_to?(:read) }
205
- mp = Multipart::MultipartPost.new
206
- query, headers = mp.prepare_query(params)
207
- Net::HTTP.start(url.host, url.port) do |http|
208
- return http.post(url.path, query, headers).body
209
- end
210
- else
211
- return Net::HTTP.post_form(url, params).body
212
- end
213
- end
214
-
215
- def check_hosts_configuration
216
- begin
217
- ok = Resolv.getaddress("passenger.test") == "127.0.0.1"
218
- ok = ok && Resolv.getaddress("1.passenger.test") == "127.0.0.1"
219
- rescue Resolv::ResolvError, ArgumentError
220
- # There's a bug in Ruby 1.8.6-p287's resolv.rb library, which causes
221
- # an ArgumentError to be raised instead of ResolvError when resolving
222
- # failed.
223
- ok = false
224
- end
225
- if !ok
226
- message = "To run the integration test, you must update " <<
227
- "your hosts file.\n" <<
228
- "Please add these to your /etc/hosts:\n\n" <<
229
- "127.0.0.1 passenger.test\n" <<
230
- "127.0.0.1 1.passenger.test 2.passenger.test 3.passenger.test\n" <<
231
- "127.0.0.1 4.passenger.test 5.passenger.test 6.passenger.test\n" <<
232
- "127.0.0.1 7.passenger.test 8.passenger.test 9.passenger.test\n"
233
- if RUBY_PLATFORM =~ /darwin/
234
- message << "\n\nThen run:\n\n" <<
235
- " dscacheutil -flushcache"
236
- end
237
- STDERR.puts "---------------------------"
238
- STDERR.puts message
239
- exit!
240
- end
241
- end
242
-
243
-
244
- ######## Other helpers ########
245
-
246
- def when_user_switching_possible
247
- if Process.euid == 0
248
- yield
249
- end
250
- end
251
-
252
- alias when_running_as_root when_user_switching_possible
253
-
254
- def when_not_running_as_root
255
- if Process.euid != 0
256
- yield
257
- end
258
- end
259
-
260
- def eventually(deadline_duration = 2, check_interval = 0.05)
261
- deadline = Time.now + deadline_duration
262
- while Time.now < deadline
263
- if yield
264
- return
265
- else
266
- sleep(check_interval)
267
- end
268
- end
269
- raise "Time limit exceeded"
270
- end
271
-
272
- def should_never_happen(deadline_duration = 1, check_interval = 0.05)
273
- deadline = Time.now + deadline_duration
274
- while Time.now < deadline
275
- if yield
276
- raise "That which shouldn't happen happened anyway"
277
- else
278
- sleep(check_interval)
279
- end
280
- end
281
- end
282
-
283
- def remove_dir_tree(dir)
284
- # FileUtils.chmod_R is susceptible to race conditions:
285
- # if another thread/process deletes a file just before
286
- # chmod_R has chmodded it, then chmod_R will raise an error.
287
- # Keep trying until a real error has been reached or until
288
- # chmod_R is done.
289
- done = false
290
- while !done
291
- begin
292
- FileUtils.chmod_R(0777, dir)
293
- done = true
294
- rescue Errno::ENOENT
295
- done = !File.exist?(dir)
296
- end
297
- end
298
- FileUtils.rm_rf(dir)
299
- end
300
-
301
- def spawn_process(*args)
302
- args.map! do |arg|
303
- arg.to_s
304
- end
305
- if Process.respond_to?(:spawn)
306
- return Process.spawn(*args)
307
- else
308
- return fork do
309
- exec(*args)
310
- end
311
- end
312
- end
313
-
314
- # Run a script in a Ruby subprocess. *args are program arguments to
315
- # pass to the script. Returns the script's stdout output.
316
- def run_script(code, *args)
317
- stdin_child, stdin_parent = IO.pipe
318
- stdout_parent, stdout_child = IO.pipe
319
- program_args = [PhusionPassenger::PlatformInfo.ruby_command, "-e",
320
- "eval(STDIN.read, binding, '(script)', 0)",
321
- PhusionPassenger::LIBDIR, *args]
322
- if Process.respond_to?(:spawn)
323
- program_args << {
324
- STDIN => stdin_child,
325
- STDOUT => stdout_child,
326
- STDERR => STDERR,
327
- :close_others => true
328
- }
329
- pid = Process.spawn(*program_args)
330
- else
331
- pid = fork do
332
- stdin_parent.close
333
- stdout_parent.close
334
- STDIN.reopen(stdin_child)
335
- STDOUT.reopen(stdout_child)
336
- stdin_child.close
337
- stdout_child.close
338
- exec(*program_args)
339
- end
340
- end
341
- stdin_child.close
342
- stdout_child.close
343
- stdin_parent.write(
344
- %Q[require(ARGV.shift + "/phusion_passenger")
345
- #{code}])
346
- stdin_parent.close
347
- result = stdout_parent.read
348
- stdout_parent.close
349
- Process.waitpid(pid)
350
- return result
351
- rescue Exception
352
- Process.kill('SIGKILL', pid) if pid
353
- raise
354
- ensure
355
- [stdin_child, stdout_child, stdin_parent, stdout_parent].each do |io|
356
- io.close if io && !io.closed?
357
- end
358
- begin
359
- Process.waitpid(pid) if pid
360
- rescue Errno::ECHILD, Errno::ESRCH
361
- end
362
- end
363
-
364
- def spawn_logging_agent(tmpdir, dump_file, password)
365
- socket_filename = "#{tmpdir}/logging.socket"
366
- password_filename = "#{tmpdir}/password"
367
- File.write(password_filename, password)
368
- pid = spawn_process("#{PhusionPassenger.support_binaries_dir}/#{PhusionPassenger::AGENT_EXE}",
369
- "logger",
370
- "--passenger-root", PhusionPassenger.install_spec,
371
- "--log-level", PhusionPassenger::DebugLogging.log_level,
372
- "--dump-file", dump_file,
373
- "--user", CONFIG['normal_user_1'],
374
- "--group", CONFIG['normal_group_1'],
375
- "--listen", "unix:#{socket_filename}",
376
- "--password-file", password_filename)
377
- eventually do
378
- File.exist?(socket_filename)
379
- end
380
- return [pid, socket_filename, "unix:#{socket_filename}"]
381
- rescue Exception => e
382
- if pid
383
- Process.kill('KILL', pid)
384
- Process.waitpid(pid)
385
- end
386
- raise e
387
- end
388
-
389
- def flush_logging_agent(password, socket_address)
390
- PhusionPassenger.require_passenger_lib 'message_client' if !defined?(PhusionPassenger::MessageClient)
391
- client = PhusionPassenger::MessageClient.new("logging", password, socket_address)
392
- begin
393
- client.write("flush")
394
- client.read
395
- ensure
396
- client.close
397
- end
398
- end
399
-
400
- def inspect_server(name)
401
- instance = PhusionPassenger::AdminTools::ServerInstance.list.first
402
- if name
403
- instance.connect(:passenger_status) do
404
- return instance.send(name)
405
- end
406
- else
407
- return instance
408
- end
409
- end
410
-
411
- if "".respond_to?(:force_encoding)
412
- def binary_string(str)
413
- return str.force_encoding("binary")
414
- end
415
- else
416
- def binary_string(str)
417
- return str
418
- end
419
- end
21
+ ######## Stub helpers ########
22
+
23
+ class Stub
24
+ attr_reader :app_root
25
+ attr_reader :full_app_root
26
+
27
+ def self.use(name, app_root = nil)
28
+ stub = new(name, app_root)
29
+ begin
30
+ yield stub
31
+ ensure
32
+ stub.destroy
33
+ end
34
+ end
35
+
36
+ def initialize(name, app_root = nil)
37
+ @name = name
38
+ if !File.exist?(stub_source_dir)
39
+ raise Errno::ENOENT, "Stub '#{name}' not found."
40
+ end
41
+
42
+ if app_root
43
+ @app_root = app_root
44
+ else
45
+ identifier = name.gsub('/', '-')
46
+ @app_root = "tmp.#{identifier}.#{object_id}"
47
+ end
48
+ @full_app_root = File.expand_path(@app_root)
49
+ remove_dir_tree(@full_app_root)
50
+ FileUtils.mkdir_p(@full_app_root)
51
+ copy_stub_contents
52
+ system("chmod", "-R", "a+rw", @full_app_root)
53
+ end
54
+
55
+ def reset
56
+ # Empty directory without removing the directory itself,
57
+ # allowing processes with this directory as current working
58
+ # directory to continue to function properly.
59
+ files = Dir["#{@full_app_root}/*"]
60
+ files |= Dir["#{@full_app_root}/.*"]
61
+ files.delete("#{@full_app_root}/.")
62
+ files.delete("#{@full_app_root}/..")
63
+ FileUtils.chmod_R(0777, files)
64
+ FileUtils.rm_rf(files)
65
+
66
+ copy_stub_contents
67
+ system("chmod", "-R", "a+rw", @full_app_root)
68
+ end
69
+
70
+ def move(new_app_root)
71
+ File.rename(@full_app_root, new_app_root)
72
+ @app_root = new_app_root
73
+ @full_app_root = File.expand_path(new_app_root)
74
+ end
75
+
76
+ def destroy
77
+ remove_dir_tree(@full_app_root)
78
+ end
79
+
80
+ def full_app_root
81
+ return File.expand_path(@app_root)
82
+ end
83
+
84
+ def public_file(name)
85
+ return File.binread("#{@full_app_root}/public/#{name}")
86
+ end
87
+
88
+ private
89
+ def stub_source_dir
90
+ return "stub/#{@name}"
91
+ end
92
+
93
+ def copy_stub_contents
94
+ FileUtils.cp_r("#{stub_source_dir}/.", @full_app_root)
95
+ end
96
+ end
97
+
98
+ class RackStub < Stub
99
+ def startup_file
100
+ return "#{@full_app_root}/config.ru"
101
+ end
102
+
103
+ private
104
+ def copy_stub_contents
105
+ super
106
+ if PhusionPassenger.build_system_dir
107
+ build_system_dir = PhusionPassenger.build_system_dir
108
+ if !File.exist?("#{@full_app_root}/Gemfile")
109
+ FileUtils.cp("#{build_system_dir}/Gemfile", @full_app_root)
110
+ FileUtils.cp("#{build_system_dir}/Gemfile.lock", @full_app_root)
111
+ if File.exist?("#{build_system_dir}/.bundle")
112
+ FileUtils.cp_r("#{build_system_dir}/.bundle", @full_app_root)
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ class PythonStub < Stub
120
+ def startup_file
121
+ return "#{@full_app_root}/passenger_wsgi.py"
122
+ end
123
+ end
124
+
125
+ class NodejsStub < Stub
126
+ def startup_file
127
+ return "#{@full_app_root}/app.js"
128
+ end
129
+ end
130
+
131
+ def describe_rails_versions(matcher, &block)
132
+ if ENV['ONLY_RAILS_VERSION'] && !ENV['ONLY_RAILS_VERSION'].empty?
133
+ found_versions = [ENV['ONLY_RAILS_VERSION']]
134
+ else
135
+ found_versions = Dir.entries("stub/rails_apps").grep(/^\d+\.\d+$/)
136
+ if RUBY_VERSION >= '1.9.0'
137
+ # Only Rails >= 2.3 is compatible with Ruby 1.9.
138
+ found_versions.reject! do |version|
139
+ version < '2.3'
140
+ end
141
+ elsif RUBY_VERSION <= '1.8.6'
142
+ # Rails >= 3 dropped support for 1.8.6 and older.
143
+ found_versions.reject! do |version|
144
+ version >= '3.0'
145
+ end
146
+ end
147
+ end
148
+
149
+ case matcher
150
+ when /^<= (.+)$/
151
+ max_version = $1
152
+ found_versions.reject! do |version|
153
+ version > max_version
154
+ end
155
+ when /^>= (.+)$/
156
+ min_version = $1
157
+ found_versions.reject! do |version|
158
+ version < min_version
159
+ end
160
+ when /^= (.+)$/
161
+ exact_version = $1
162
+ found_versions.reject! do |version|
163
+ version != exact_version
164
+ end
165
+ else
166
+ raise ArgumentError, "Unknown matcher string '#{matcher}'"
167
+ end
168
+
169
+ found_versions.sort.each do |version|
170
+ klass = describe("Rails #{version}", &block)
171
+ klass.send(:define_method, :rails_version) do
172
+ version
173
+ end
174
+ end
175
+ end
176
+
177
+
178
+ ######## HTTP helpers ########
179
+ # Before using these methods, one must set the '@server' instance variable
180
+ # and implement the start_web_server_if_necessary method.
181
+
182
+ def get(uri)
183
+ if @server.nil?
184
+ raise "You must set the '@server' instance variable before get() can be used. For example, @server = 'http://mydomain.test/'"
185
+ end
186
+ start_web_server_if_necessary
187
+ return Net::HTTP.get(URI.parse("#{@server}#{uri}"))
188
+ end
189
+
190
+ def get_response(uri)
191
+ if @server.nil?
192
+ raise "You must set the '@server' instance variable before get() can be used. For example, @server = 'http://mydomain.test/'"
193
+ end
194
+ start_web_server_if_necessary
195
+ return Net::HTTP.get_response(URI.parse("#{@server}#{uri}"))
196
+ end
197
+
198
+ def post(uri, params = {})
199
+ if @server.nil?
200
+ raise "You must set the '@server' instance variable before get() can be used. For example, @server = 'http://mydomain.test/'"
201
+ end
202
+ start_web_server_if_necessary
203
+ url = URI.parse("#{@server}#{uri}")
204
+ if params.values.any? { |x| x.respond_to?(:read) }
205
+ mp = Multipart::MultipartPost.new
206
+ query, headers = mp.prepare_query(params)
207
+ Net::HTTP.start(url.host, url.port) do |http|
208
+ return http.post(url.path, query, headers).body
209
+ end
210
+ else
211
+ return Net::HTTP.post_form(url, params).body
212
+ end
213
+ end
214
+
215
+ def check_hosts_configuration
216
+ begin
217
+ ok = Resolv.getaddress("passenger.test") == "127.0.0.1"
218
+ ok = ok && Resolv.getaddress("1.passenger.test") == "127.0.0.1"
219
+ rescue Resolv::ResolvError, ArgumentError
220
+ # There's a bug in Ruby 1.8.6-p287's resolv.rb library, which causes
221
+ # an ArgumentError to be raised instead of ResolvError when resolving
222
+ # failed.
223
+ ok = false
224
+ end
225
+ if !ok
226
+ message = "To run the integration test, you must update " <<
227
+ "your hosts file.\n" <<
228
+ "Please add these to your /etc/hosts:\n\n" <<
229
+ "127.0.0.1 passenger.test\n" <<
230
+ "127.0.0.1 1.passenger.test 2.passenger.test 3.passenger.test\n" <<
231
+ "127.0.0.1 4.passenger.test 5.passenger.test 6.passenger.test\n" <<
232
+ "127.0.0.1 7.passenger.test 8.passenger.test 9.passenger.test\n"
233
+ if RUBY_PLATFORM =~ /darwin/
234
+ message << "\n\nThen run:\n\n" <<
235
+ " dscacheutil -flushcache"
236
+ end
237
+ STDERR.puts "---------------------------"
238
+ STDERR.puts message
239
+ exit!
240
+ end
241
+ end
242
+
243
+
244
+ ######## Other helpers ########
245
+
246
+ def when_user_switching_possible
247
+ if Process.euid == 0
248
+ yield
249
+ end
250
+ end
251
+
252
+ alias when_running_as_root when_user_switching_possible
253
+
254
+ def when_not_running_as_root
255
+ if Process.euid != 0
256
+ yield
257
+ end
258
+ end
259
+
260
+ def eventually(deadline_duration = 2, check_interval = 0.05)
261
+ deadline = Time.now + deadline_duration
262
+ while Time.now < deadline
263
+ if yield
264
+ return
265
+ else
266
+ sleep(check_interval)
267
+ end
268
+ end
269
+ raise "Time limit exceeded"
270
+ end
271
+
272
+ def should_never_happen(deadline_duration = 1, check_interval = 0.05)
273
+ deadline = Time.now + deadline_duration
274
+ while Time.now < deadline
275
+ if yield
276
+ raise "That which shouldn't happen happened anyway"
277
+ else
278
+ sleep(check_interval)
279
+ end
280
+ end
281
+ end
282
+
283
+ def remove_dir_tree(dir)
284
+ # FileUtils.chmod_R is susceptible to race conditions:
285
+ # if another thread/process deletes a file just before
286
+ # chmod_R has chmodded it, then chmod_R will raise an error.
287
+ # Keep trying until a real error has been reached or until
288
+ # chmod_R is done.
289
+ done = false
290
+ while !done
291
+ begin
292
+ FileUtils.chmod_R(0777, dir)
293
+ done = true
294
+ rescue Errno::ENOENT
295
+ done = !File.exist?(dir)
296
+ end
297
+ end
298
+ FileUtils.rm_rf(dir)
299
+ end
300
+
301
+ def spawn_process(*args)
302
+ args.map! do |arg|
303
+ arg.to_s
304
+ end
305
+ if Process.respond_to?(:spawn)
306
+ return Process.spawn(*args)
307
+ else
308
+ return fork do
309
+ exec(*args)
310
+ end
311
+ end
312
+ end
313
+
314
+ # Run a script in a Ruby subprocess. *args are program arguments to
315
+ # pass to the script. Returns the script's stdout output.
316
+ def run_script(code, *args)
317
+ stdin_child, stdin_parent = IO.pipe
318
+ stdout_parent, stdout_child = IO.pipe
319
+ program_args = [PhusionPassenger::PlatformInfo.ruby_command, "-e",
320
+ "eval(STDIN.read, binding, '(script)', 0)",
321
+ PhusionPassenger::LIBDIR, *args]
322
+ if Process.respond_to?(:spawn)
323
+ program_args << {
324
+ STDIN => stdin_child,
325
+ STDOUT => stdout_child,
326
+ STDERR => STDERR,
327
+ :close_others => true
328
+ }
329
+ pid = Process.spawn(*program_args)
330
+ else
331
+ pid = fork do
332
+ stdin_parent.close
333
+ stdout_parent.close
334
+ STDIN.reopen(stdin_child)
335
+ STDOUT.reopen(stdout_child)
336
+ stdin_child.close
337
+ stdout_child.close
338
+ exec(*program_args)
339
+ end
340
+ end
341
+ stdin_child.close
342
+ stdout_child.close
343
+ stdin_parent.write(
344
+ %Q[require(ARGV.shift + "/phusion_passenger")
345
+ #{code}])
346
+ stdin_parent.close
347
+ result = stdout_parent.read
348
+ stdout_parent.close
349
+ Process.waitpid(pid)
350
+ return result
351
+ rescue Exception
352
+ Process.kill('SIGKILL', pid) if pid
353
+ raise
354
+ ensure
355
+ [stdin_child, stdout_child, stdin_parent, stdout_parent].each do |io|
356
+ io.close if io && !io.closed?
357
+ end
358
+ begin
359
+ Process.waitpid(pid) if pid
360
+ rescue Errno::ECHILD, Errno::ESRCH
361
+ end
362
+ end
363
+
364
+ def spawn_logging_agent(tmpdir, dump_file, password)
365
+ socket_filename = "#{tmpdir}/logging.socket"
366
+ password_filename = "#{tmpdir}/password"
367
+ File.write(password_filename, password)
368
+ pid = spawn_process("#{PhusionPassenger.support_binaries_dir}/#{PhusionPassenger::AGENT_EXE}",
369
+ "logger",
370
+ "--passenger-root", PhusionPassenger.install_spec,
371
+ "--log-level", PhusionPassenger::DebugLogging.log_level,
372
+ "--dump-file", dump_file,
373
+ "--user", CONFIG['normal_user_1'],
374
+ "--group", CONFIG['normal_group_1'],
375
+ "--listen", "unix:#{socket_filename}",
376
+ "--password-file", password_filename)
377
+ eventually do
378
+ File.exist?(socket_filename)
379
+ end
380
+ return [pid, socket_filename, "unix:#{socket_filename}"]
381
+ rescue Exception => e
382
+ if pid
383
+ Process.kill('KILL', pid)
384
+ Process.waitpid(pid)
385
+ end
386
+ raise e
387
+ end
388
+
389
+ def flush_logging_agent(password, socket_address)
390
+ PhusionPassenger.require_passenger_lib 'message_client' if !defined?(PhusionPassenger::MessageClient)
391
+ client = PhusionPassenger::MessageClient.new("logging", password, socket_address)
392
+ begin
393
+ client.write("flush")
394
+ client.read
395
+ ensure
396
+ client.close
397
+ end
398
+ end
399
+
400
+ def inspect_server(name)
401
+ instance = PhusionPassenger::AdminTools::ServerInstance.list.first
402
+ if name
403
+ instance.connect(:passenger_status) do
404
+ return instance.send(name)
405
+ end
406
+ else
407
+ return instance
408
+ end
409
+ end
410
+
411
+ if "".respond_to?(:force_encoding)
412
+ def binary_string(str)
413
+ return str.force_encoding("binary")
414
+ end
415
+ else
416
+ def binary_string(str)
417
+ return str
418
+ end
419
+ end
420
420
  end
421
421
 
422
422
  File.class_eval do
423
- def self.prepend(filename, data)
424
- original_content = File.read(filename)
425
- File.open(filename, 'w') do |f|
426
- f.write(data)
427
- f.write(original_content)
428
- end
429
- end
430
-
431
- def self.append(filename, data)
432
- File.open(filename, 'a') do |f|
433
- f.write(data)
434
- end
435
- end
436
-
437
- def self.write(filename, content = nil)
438
- if block_given?
439
- content = yield File.read(filename)
440
- end
441
- File.open(filename, 'w') do |f|
442
- f.write(content)
443
- end
444
- end
445
-
446
- def self.touch(filename, timestamp = nil)
447
- File.open(filename, 'w').close
448
- File.utime(timestamp, timestamp, filename) if timestamp
449
- end
450
-
451
- def self.binread(filename)
452
- return File.read(filename)
453
- end if !respond_to?(:binread)
423
+ def self.prepend(filename, data)
424
+ original_content = File.read(filename)
425
+ File.open(filename, 'w') do |f|
426
+ f.write(data)
427
+ f.write(original_content)
428
+ end
429
+ end
430
+
431
+ def self.append(filename, data)
432
+ File.open(filename, 'a') do |f|
433
+ f.write(data)
434
+ end
435
+ end
436
+
437
+ def self.write(filename, content = nil)
438
+ if block_given?
439
+ content = yield File.read(filename)
440
+ end
441
+ File.open(filename, 'w') do |f|
442
+ f.write(content)
443
+ end
444
+ end
445
+
446
+ def self.touch(filename, timestamp = nil)
447
+ File.open(filename, 'w').close
448
+ File.utime(timestamp, timestamp, filename) if timestamp
449
+ end
450
+
451
+ def self.binread(filename)
452
+ return File.read(filename)
453
+ end if !respond_to?(:binread)
454
454
  end
455
455