passenger 2.2.2 → 2.2.3

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 (254) hide show
  1. data/DEVELOPERS.TXT +13 -3
  2. data/Rakefile +42 -33
  3. data/bin/passenger-install-apache2-module +1 -2
  4. data/bin/passenger-install-nginx-module +7 -19
  5. data/bin/passenger-status +64 -15
  6. data/bin/passenger-stress-test +2 -2
  7. data/doc/ApplicationPool algorithm.txt +26 -22
  8. data/doc/Users guide Apache.html +374 -149
  9. data/doc/Users guide Apache.txt +318 -51
  10. data/doc/Users guide Nginx.html +13 -13
  11. data/doc/Users guide Nginx.txt +7 -2
  12. data/doc/cxxapi/Bucket_8h-source.html +62 -25
  13. data/doc/cxxapi/Configuration_8h-source.html +343 -326
  14. data/doc/cxxapi/DirectoryMapper_8h-source.html +12 -12
  15. data/doc/cxxapi/Hooks_8h-source.html +1 -1
  16. data/doc/cxxapi/annotated.html +1 -1
  17. data/doc/cxxapi/classHooks-members.html +1 -1
  18. data/doc/cxxapi/classHooks.html +1 -1
  19. data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +2 -2
  20. data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +9 -9
  21. data/doc/cxxapi/classes.html +1 -1
  22. data/doc/cxxapi/definitions_8h-source.html +1 -1
  23. data/doc/cxxapi/files.html +1 -1
  24. data/doc/cxxapi/functions.html +2 -2
  25. data/doc/cxxapi/functions_func.html +2 -2
  26. data/doc/cxxapi/graph_legend.html +1 -1
  27. data/doc/cxxapi/group__Configuration.html +1 -1
  28. data/doc/cxxapi/group__Core.html +1 -1
  29. data/doc/cxxapi/group__Hooks.html +1 -1
  30. data/doc/cxxapi/group__Support.html +1 -1
  31. data/doc/cxxapi/main.html +1 -1
  32. data/doc/cxxapi/modules.html +1 -1
  33. data/doc/rdoc/classes/ConditionVariable.html +194 -0
  34. data/doc/rdoc/classes/Exception.html +120 -0
  35. data/doc/rdoc/classes/GC.html +113 -0
  36. data/doc/rdoc/classes/IO.html +169 -0
  37. data/doc/rdoc/classes/PhusionPassenger.html +238 -0
  38. data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +153 -0
  39. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +517 -0
  40. data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +719 -0
  41. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerAlreadyStarted.html +97 -0
  42. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerError.html +96 -0
  43. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerNotStarted.html +97 -0
  44. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/UnknownMessage.html +96 -0
  45. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +598 -0
  46. data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +140 -0
  47. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +317 -0
  48. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess/Instance.html +138 -0
  49. data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +154 -0
  50. data/doc/rdoc/classes/PhusionPassenger/Application.html +283 -0
  51. data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +172 -0
  52. data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +145 -0
  53. data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +175 -0
  54. data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +141 -0
  55. data/doc/rdoc/classes/PhusionPassenger/InvalidPath.html +92 -0
  56. data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +489 -0
  57. data/doc/rdoc/classes/PhusionPassenger/NativeSupport.html +350 -0
  58. data/doc/rdoc/classes/PhusionPassenger/Rack.html +91 -0
  59. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +188 -0
  60. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +194 -0
  61. data/doc/rdoc/classes/PhusionPassenger/Railz.html +95 -0
  62. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +442 -0
  63. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner/Error.html +98 -0
  64. data/doc/rdoc/classes/PhusionPassenger/Railz/CGIFixed.html +200 -0
  65. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +436 -0
  66. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner/Error.html +98 -0
  67. data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +155 -0
  68. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +402 -0
  69. data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +125 -0
  70. data/doc/rdoc/classes/PhusionPassenger/Utils.html +805 -0
  71. data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +140 -0
  72. data/doc/rdoc/classes/PhusionPassenger/WSGI.html +89 -0
  73. data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +188 -0
  74. data/doc/rdoc/classes/PlatformInfo.html +831 -0
  75. data/doc/rdoc/classes/RakeExtensions.html +197 -0
  76. data/doc/rdoc/classes/Signal.html +131 -0
  77. data/doc/rdoc/created.rid +1 -0
  78. data/doc/rdoc/files/DEVELOPERS_TXT.html +255 -0
  79. data/doc/rdoc/files/README.html +157 -0
  80. data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +92 -0
  81. data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +129 -0
  82. data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +131 -0
  83. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +126 -0
  84. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +130 -0
  85. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +130 -0
  86. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +122 -0
  87. data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +127 -0
  88. data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +126 -0
  89. data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +122 -0
  90. data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +134 -0
  91. data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +122 -0
  92. data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +122 -0
  93. data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +126 -0
  94. data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +122 -0
  95. data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +122 -0
  96. data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +127 -0
  97. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +133 -0
  98. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +127 -0
  99. data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +143 -0
  100. data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +126 -0
  101. data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +145 -0
  102. data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +127 -0
  103. data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +122 -0
  104. data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +161 -0
  105. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +175 -0
  106. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +129 -0
  107. data/doc/rdoc/files/misc/rake/extensions_rb.html +130 -0
  108. data/doc/rdoc/fr_class_index.html +90 -0
  109. data/doc/rdoc/fr_file_index.html +76 -0
  110. data/doc/rdoc/fr_method_index.html +200 -0
  111. data/doc/rdoc/index.html +26 -0
  112. data/doc/rdoc/rdoc-style.css +187 -0
  113. data/doc/users_guide_snippets/rackup_specifications.txt +2 -8
  114. data/ext/apache2/Bucket.cpp +71 -38
  115. data/ext/apache2/Bucket.h +53 -16
  116. data/ext/apache2/Configuration.cpp +15 -0
  117. data/ext/apache2/Configuration.h +19 -2
  118. data/ext/apache2/DirectoryMapper.h +10 -10
  119. data/ext/apache2/Hooks.cpp +334 -74
  120. data/ext/boost/mpl/apply.hpp +5 -1
  121. data/ext/boost/mpl/apply_wrap.hpp +5 -2
  122. data/ext/boost/mpl/aux_/full_lambda.hpp +5 -1
  123. data/ext/boost/mpl/bind.hpp +5 -1
  124. data/ext/common/Application.h +11 -31
  125. data/ext/common/ApplicationPool.h +2 -1
  126. data/ext/common/ApplicationPoolServer.h +61 -20
  127. data/ext/common/ApplicationPoolServerExecutable.cpp +132 -4
  128. data/ext/common/ApplicationPoolStatusReporter.h +189 -65
  129. data/ext/common/Base64.cpp +143 -0
  130. data/ext/common/Base64.h +57 -0
  131. data/ext/common/CachedFileStat.cpp +25 -82
  132. data/ext/common/CachedFileStat.h +11 -125
  133. data/ext/common/CachedFileStat.hpp +243 -0
  134. data/ext/common/Exceptions.h +13 -0
  135. data/ext/common/FileChangeChecker.h +209 -0
  136. data/ext/common/Logging.h +3 -2
  137. data/ext/common/MessageChannel.h +10 -10
  138. data/ext/common/PoolOptions.h +72 -5
  139. data/ext/common/SpawnManager.h +11 -8
  140. data/ext/common/StandardApplicationPool.h +38 -39
  141. data/ext/common/StaticString.h +1 -0
  142. data/ext/common/StringListCreator.h +83 -0
  143. data/ext/common/SystemTime.h +3 -2
  144. data/ext/common/Timer.h +88 -0
  145. data/ext/common/Utils.cpp +161 -42
  146. data/ext/common/Utils.h +62 -31
  147. data/ext/common/Version.h +1 -1
  148. data/ext/nginx/Configuration.c +0 -4
  149. data/ext/nginx/ContentHandler.c +8 -6
  150. data/ext/nginx/HelperServer.cpp +45 -55
  151. data/ext/nginx/HttpStatusExtractor.h +4 -0
  152. data/ext/nginx/StaticContentHandler.c +25 -5
  153. data/ext/nginx/config +3 -0
  154. data/ext/nginx/ngx_http_passenger_module.c +72 -17
  155. data/ext/nginx/ngx_http_passenger_module.h +2 -2
  156. data/lib/phusion_passenger/abstract_request_handler.rb +15 -7
  157. data/lib/phusion_passenger/abstract_server.rb +16 -2
  158. data/lib/phusion_passenger/admin_tools/control_process.rb +36 -25
  159. data/lib/phusion_passenger/constants.rb +1 -1
  160. data/lib/phusion_passenger/dependencies.rb +10 -0
  161. data/lib/phusion_passenger/platform_info.rb +1 -1
  162. data/lib/phusion_passenger/rack/application_spawner.rb +21 -2
  163. data/lib/phusion_passenger/rack/request_handler.rb +10 -0
  164. data/lib/phusion_passenger/railz/application_spawner.rb +38 -2
  165. data/lib/phusion_passenger/railz/framework_spawner.rb +26 -28
  166. data/lib/phusion_passenger/railz/request_handler.rb +5 -1
  167. data/lib/phusion_passenger/spawn_manager.rb +6 -2
  168. data/lib/phusion_passenger/utils.rb +79 -27
  169. data/misc/rake/cplusplus.rb +5 -5
  170. data/test/ApplicationPoolServerTest.cpp +42 -0
  171. data/test/ApplicationPoolTest.cpp +255 -267
  172. data/test/Base64Test.cpp +48 -0
  173. data/test/CachedFileStatTest.cpp +243 -103
  174. data/test/FileChangeCheckerTest.cpp +331 -0
  175. data/test/PoolOptionsTest.cpp +80 -0
  176. data/test/UtilsTest.cpp +5 -17
  177. data/test/integration_tests/apache2_tests.rb +15 -4
  178. data/test/integration_tests/mycook_spec.rb +3 -4
  179. data/test/oxt/syscall_interruption_test.cpp +2 -14
  180. data/test/ruby/abstract_server_collection_spec.rb +1 -1
  181. data/test/ruby/abstract_server_spec.rb +35 -1
  182. data/test/ruby/rack/application_spawner_spec.rb +23 -6
  183. data/test/ruby/rails/application_spawner_spec.rb +6 -6
  184. data/test/ruby/rails/framework_spawner_spec.rb +6 -5
  185. data/test/ruby/rails/minimal_spawner_spec.rb +19 -0
  186. data/test/ruby/rails/spawner_error_handling_spec.rb +62 -7
  187. data/test/ruby/spawn_manager_spec.rb +10 -7
  188. data/test/ruby/spawn_server_spec.rb +1 -1
  189. data/test/ruby/utils_spec.rb +193 -20
  190. data/test/ruby/wsgi/application_spawner_spec.rb +3 -1
  191. data/test/stub/apache2/httpd.conf.erb +3 -0
  192. data/test/stub/rack/config.ru +1 -1
  193. data/test/stub/rails_apps/mycook/app/controllers/welcome_controller.rb +8 -0
  194. data/test/support/Support.cpp +84 -0
  195. data/test/support/Support.h +66 -8
  196. data/test/support/config.rb +14 -2
  197. data/test/support/test_helper.rb +5 -0
  198. data/vendor/rack-1.0.0-git/lib/rack/auth/openid.rb +123 -116
  199. data/vendor/rack-1.0.0-git/lib/rack/cascade.rb +17 -12
  200. data/vendor/rack-1.0.0-git/lib/rack/commonlogger.rb +34 -43
  201. data/vendor/rack-1.0.0-git/lib/rack/handler/cgi.rb +1 -1
  202. data/vendor/rack-1.0.0-git/lib/rack/handler/fastcgi.rb +1 -1
  203. data/vendor/rack-1.0.0-git/lib/rack/handler/lsws.rb +1 -1
  204. data/vendor/rack-1.0.0-git/lib/rack/handler/mongrel.rb +1 -1
  205. data/vendor/rack-1.0.0-git/lib/rack/handler/scgi.rb +1 -1
  206. data/vendor/rack-1.0.0-git/lib/rack/handler/webrick.rb +1 -1
  207. data/vendor/rack-1.0.0-git/lib/rack/mock.rb +4 -17
  208. data/vendor/rack-1.0.0-git/lib/rack/request.rb +3 -9
  209. data/vendor/rack-1.0.0-git/lib/rack/rewindable_input.rb +2 -0
  210. data/vendor/rack-1.0.0-git/lib/rack/utils.rb +38 -12
  211. metadata +231 -186
  212. data/ext/common/FileChecker.h +0 -112
  213. data/test/FileCheckerTest.cpp +0 -79
  214. data/test/stub/minimal-railsapp/README +0 -3
  215. data/test/stub/minimal-railsapp/config/application.rb +0 -0
  216. data/test/stub/minimal-railsapp/config/environment.rb +0 -3
  217. data/test/stub/minimal-railsapp/vendor/rails/actionmailer/lib/action_mailer.rb +0 -0
  218. data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_controller.rb +0 -10
  219. data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_pack.rb +0 -0
  220. data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_view.rb +0 -0
  221. data/test/stub/minimal-railsapp/vendor/rails/activerecord/lib/active_record.rb +0 -7
  222. data/test/stub/minimal-railsapp/vendor/rails/activeresource/lib/active_resource.rb +0 -0
  223. data/test/stub/minimal-railsapp/vendor/rails/activesupport/lib/active_support.rb +0 -17
  224. data/test/stub/minimal-railsapp/vendor/rails/activesupport/lib/active_support/whiny_nil.rb +0 -0
  225. data/test/stub/minimal-railsapp/vendor/rails/railties/lib/dispatcher.rb +0 -0
  226. data/test/stub/minimal-railsapp/vendor/rails/railties/lib/initializer.rb +0 -8
  227. data/test/stub/minimal-railsapp/vendor/rails/railties/lib/ruby_version_check.rb +0 -1
  228. data/test/stub/railsapp/app/controllers/application.rb +0 -12
  229. data/test/stub/railsapp/app/controllers/bar_controller.rb +0 -5
  230. data/test/stub/railsapp/app/controllers/bar_controller_1.txt +0 -5
  231. data/test/stub/railsapp/app/controllers/bar_controller_2.txt +0 -5
  232. data/test/stub/railsapp/app/controllers/foo_controller.rb +0 -9
  233. data/test/stub/railsapp/app/helpers/application_helper.rb +0 -3
  234. data/test/stub/railsapp/config/boot.rb +0 -108
  235. data/test/stub/railsapp/config/database.yml +0 -19
  236. data/test/stub/railsapp/config/environment.rb +0 -59
  237. data/test/stub/railsapp/config/environments/development.rb +0 -18
  238. data/test/stub/railsapp/config/environments/production.rb +0 -19
  239. data/test/stub/railsapp/config/initializers/inflections.rb +0 -10
  240. data/test/stub/railsapp/config/initializers/mime_types.rb +0 -5
  241. data/test/stub/railsapp/config/routes.rb +0 -35
  242. data/test/stub/railsapp/public/useless.txt +0 -1
  243. data/test/stub/railsapp2/app/controllers/application.rb +0 -12
  244. data/test/stub/railsapp2/app/controllers/foo_controller.rb +0 -5
  245. data/test/stub/railsapp2/app/helpers/application_helper.rb +0 -3
  246. data/test/stub/railsapp2/config/boot.rb +0 -108
  247. data/test/stub/railsapp2/config/database.yml +0 -19
  248. data/test/stub/railsapp2/config/environment.rb +0 -59
  249. data/test/stub/railsapp2/config/environments/development.rb +0 -18
  250. data/test/stub/railsapp2/config/environments/production.rb +0 -19
  251. data/test/stub/railsapp2/config/initializers/inflections.rb +0 -10
  252. data/test/stub/railsapp2/config/initializers/mime_types.rb +0 -5
  253. data/test/stub/railsapp2/config/routes.rb +0 -35
  254. data/test/stub/railsapp2/public/useless.txt +0 -1
@@ -3,7 +3,7 @@ require 'support/config'
3
3
  require 'ruby/abstract_server_spec'
4
4
 
5
5
  shared_examples_for "a spawn server" do
6
- it_should_behave_like "AbstractServer"
6
+ it_should_behave_like "an AbstractServer"
7
7
 
8
8
  it "raises an AbstractServer::ServerError if the server was killed" do
9
9
  Process.kill('SIGABRT', @spawner.server_pid)
@@ -2,6 +2,8 @@ require 'support/config'
2
2
 
3
3
  require 'tmpdir'
4
4
  require 'fileutils'
5
+ require 'stringio'
6
+ require 'phusion_passenger/message_channel'
5
7
  require 'phusion_passenger/utils'
6
8
 
7
9
  include PhusionPassenger
@@ -11,36 +13,204 @@ describe Utils do
11
13
 
12
14
  specify "#close_all_io_objects_for_fds closes all IO objects that are associated with the given file descriptors" do
13
15
  filename = "#{Dir.tmpdir}/passenger_test.#{Process.pid}.txt"
14
- puts "#{$$}: 1"
15
16
  begin
16
- pid = fork do
17
- begin
18
- puts "#{$$}: 2"
19
- a, b = IO.pipe
20
- puts "#{$$}: 3"
21
- close_all_io_objects_for_fds([0, 1, 2])
22
- puts "#{$$}: 4"
23
- File.open(filename, "w") do |f|
24
- f.write("#{a.closed?}, #{b.closed?}")
25
- end
26
- puts "#{$$}: 5"
27
- rescue Exception => e
28
- print_exception("utils_spec", e)
29
- ensure
30
- puts "#{$$}: 6"
31
- exit!
17
+ pid = safe_fork('utils_spec') do
18
+ a, b = IO.pipe
19
+ close_all_io_objects_for_fds([0, 1, 2])
20
+ File.open(filename, "w") do |f|
21
+ f.write("#{a.closed?}, #{b.closed?}")
32
22
  end
33
23
  end
34
- puts "#{$$}: 6"
35
24
  Process.waitpid(pid) rescue nil
36
- puts "#{$$}: 7"
37
25
  File.read(filename).should == "true, true"
38
26
  ensure
39
- puts "#{$$}: 8"
40
27
  File.unlink(filename) rescue nil
41
28
  end
42
29
  end
43
30
 
31
+ describe "#report_app_init_status" do
32
+ it "reports normal errors, which #unmarshal_and_raise_errors raises" do
33
+ a, b = IO.pipe
34
+ begin
35
+ pid = safe_fork('utils_spec') do
36
+ a.close
37
+ report_app_init_status(MessageChannel.new(b)) do
38
+ raise RuntimeError, "hello world"
39
+ end
40
+ end
41
+ b.close
42
+ lambda { unmarshal_and_raise_errors(MessageChannel.new(a)) }.should raise_error(/hello world/)
43
+ ensure
44
+ a.close rescue nil
45
+ b.close rescue nil
46
+ end
47
+ end
48
+
49
+ it "reports SystemExit errors, which #unmarshal_and_raise_errors raises" do
50
+ a, b = IO.pipe
51
+ begin
52
+ pid = safe_fork('utils_spec') do
53
+ a.close
54
+ report_app_init_status(MessageChannel.new(b)) do
55
+ exit
56
+ end
57
+ end
58
+ b.close
59
+ lambda { unmarshal_and_raise_errors(MessageChannel.new(a)) }.should raise_error(/exited during startup/)
60
+ ensure
61
+ a.close rescue nil
62
+ b.close rescue nil
63
+ end
64
+ end
65
+
66
+ it "returns whether the block succeeded" do
67
+ channel = MessageChannel.new(StringIO.new)
68
+ success = report_app_init_status(channel) do
69
+ false
70
+ end
71
+ success.should be_true
72
+
73
+ success = report_app_init_status(channel) do
74
+ raise StandardError, "hi"
75
+ end
76
+ success.should be_false
77
+ end
78
+
79
+ it "reports all data written to stderr" do
80
+ a, b = IO.pipe
81
+ begin
82
+ pid = safe_fork('utils_spec') do
83
+ a.close
84
+ report_app_init_status(MessageChannel.new(b)) do
85
+ STDERR.puts "Something went wrong!"
86
+ exit
87
+ end
88
+ end
89
+ b.close
90
+
91
+ begin
92
+ unmarshal_and_raise_errors(MessageChannel.new(a))
93
+ violated "No exception raised"
94
+ rescue AppInitError => e
95
+ e.stderr.should =~ /Something went wrong!/
96
+ end
97
+ ensure
98
+ a.close rescue nil
99
+ b.close rescue nil
100
+ end
101
+ end
102
+
103
+ it "writes all buffered stderr data to the 'write_stderr_contents_to' argument if the block failed" do
104
+ stderr_buffer = StringIO.new
105
+ report_app_init_status(MessageChannel.new(StringIO.new), stderr_buffer) do
106
+ STDERR.puts "Something went wrong!"
107
+ raise StandardError, ":-("
108
+ end
109
+
110
+ stderr_buffer.string.should =~ /Something went wrong!/
111
+ end
112
+
113
+ it "writes all buffered stderr data to the 'write_stderr_contents_to' argument if the block succeeded" do
114
+ stderr_buffer = StringIO.new
115
+ report_app_init_status(MessageChannel.new(StringIO.new), stderr_buffer) do
116
+ STDERR.puts "Something went wrong!"
117
+ end
118
+
119
+ stderr_buffer.string.should =~ /Something went wrong!/
120
+ end
121
+ end
122
+
123
+ specify "#safe_fork with double_fork == false reseeds the pseudo-random number generator" do
124
+ a, b = IO.pipe
125
+ begin
126
+ pid = safe_fork do
127
+ b.puts(rand)
128
+ end
129
+ Process.waitpid(pid) rescue nil
130
+ pid = safe_fork do
131
+ b.puts(rand)
132
+ end
133
+ Process.waitpid(pid) rescue nil
134
+
135
+ first_num = a.readline
136
+ second_num = a.readline
137
+ first_num.should_not == second_num
138
+ ensure
139
+ a.close rescue nil
140
+ b.close rescue nil
141
+ end
142
+ end
143
+
144
+ specify "#safe_fork with double_fork == true reseeds the pseudo-random number generator" do
145
+ a, b = IO.pipe
146
+ begin
147
+ # Seed the pseudo-random number generator here
148
+ # so that it doesn't happen in the child processes.
149
+ srand
150
+
151
+ safe_fork(self.class, true) do
152
+ b.puts(rand)
153
+ end
154
+ safe_fork(self.class, true) do
155
+ b.puts(rand)
156
+ end
157
+
158
+ first_num = a.readline
159
+ second_num = a.readline
160
+ first_num.should_not == second_num
161
+ ensure
162
+ a.close rescue nil
163
+ b.close rescue nil
164
+ end
165
+ end
166
+
167
+ describe "#unmarshal_and_raise_errors" do
168
+ before :each do
169
+ @a, @b = IO.pipe
170
+ @report_channel = MessageChannel.new(@a)
171
+ report_app_init_status(MessageChannel.new(@b)) do
172
+ raise StandardError, "Something went wrong!"
173
+ end
174
+ end
175
+
176
+ after :each do
177
+ @a.close rescue nil
178
+ @b.close rescue nil
179
+ end
180
+
181
+ it "prints the exception information to the 'print_exception' argument using #puts, if 'print_exception' responds to that" do
182
+ buffer = StringIO.new
183
+ lambda { unmarshal_and_raise_errors(@report_channel, buffer) }.should raise_error(AppInitError)
184
+ buffer.string.should =~ /Something went wrong!/
185
+ buffer.string.should =~ /utils\.rb/
186
+ buffer.string.should =~ /utils_spec\.rb/
187
+ end
188
+
189
+ it "appends the exception information to the file pointed to by 'print_exception', if 'print_exception' responds to #to_str" do
190
+ begin
191
+ lambda { unmarshal_and_raise_errors(@report_channel, "exception.txt") }.should raise_error(AppInitError)
192
+ data = File.read('exception.txt')
193
+ data.should =~ /Something went wrong!/
194
+ data.should =~ /utils\.rb/
195
+ data.should =~ /utils_spec\.rb/
196
+ ensure
197
+ File.unlink('exception.txt') rescue nil
198
+ end
199
+ end
200
+ end
201
+
202
+ specify "#to_boolean works" do
203
+ to_boolean(nil).should be_false
204
+ to_boolean(false).should be_false
205
+ to_boolean(true).should be_true
206
+ to_boolean(1).should be_true
207
+ to_boolean(0).should be_true
208
+ to_boolean("").should be_true
209
+ to_boolean("true").should be_true
210
+ to_boolean("false").should be_false
211
+ to_boolean("bla bla").should be_true
212
+ end
213
+
44
214
  describe "#passenger_tmpdir" do
45
215
  before :each do
46
216
  @old_passenger_tmpdir = Utils.passenger_tmpdir
@@ -71,8 +241,11 @@ describe Utils do
71
241
  begin
72
242
  File.directory?('utils_spec.tmp').should be_true
73
243
  ensure
244
+ FileUtils.chmod_R(0777, 'utils_spec.tmp')
74
245
  FileUtils.rm_rf('utils_spec.tmp')
75
246
  end
76
247
  end
77
248
  end
249
+
250
+ ######################
78
251
  end
@@ -5,6 +5,8 @@ require 'phusion_passenger/utils'
5
5
  require 'fileutils'
6
6
  require 'tempfile'
7
7
 
8
+ include PhusionPassenger
9
+
8
10
  describe PhusionPassenger::WSGI::ApplicationSpawner do
9
11
  include TestHelper
10
12
  include PhusionPassenger::Utils
@@ -39,7 +41,7 @@ describe PhusionPassenger::WSGI::ApplicationSpawner do
39
41
 
40
42
  specify "the backend process deletes its socket upon termination" do
41
43
  spawn(@stub.app_root).close
42
- sleep 0.2 # Give it some time to terminate.
44
+ sleep 0.25 # Give it some time to terminate.
43
45
  File.chmod(0700, "#{passenger_tmpdir}/backends")
44
46
  Dir["#{passenger_tmpdir}/backends/wsgi_backend.*"].should be_empty
45
47
  end
@@ -23,6 +23,9 @@ Listen 127.0.0.1:<%= @port %>
23
23
  <% if !has_builtin_module?('mod_rewrite.c') && has_module?('mod_rewrite.so') %>
24
24
  LoadModule rewrite_module "<%= modules_dir %>/mod_rewrite.so"
25
25
  <% end %>
26
+ <% if !has_builtin_module?('mod_env.c') %>
27
+ LoadModule env_module "<%= modules_dir %>/mod_env.so"
28
+ <% end %>
26
29
  LoadModule passenger_module "<%= @mod_passenger %>"
27
30
 
28
31
  PassengerRoot "<%= @passenger_root %>"
@@ -1,4 +1,4 @@
1
1
  app = lambda do |env|
2
- return [200, { "Content-Type" => "text/html" }, "hello <b>world</b>"]
2
+ [200, { "Content-Type" => "text/html" }, ["hello <b>world</b>"]]
3
3
  end
4
4
  run app
@@ -40,6 +40,14 @@ class WelcomeController < ApplicationController
40
40
  def show_id
41
41
  render :text => params[:id]
42
42
  end
43
+
44
+ def environment
45
+ text = ""
46
+ ENV.each_pair do |key, value|
47
+ text << "#{key} = #{value}\n"
48
+ end
49
+ render :text => text
50
+ end
43
51
 
44
52
  def request_uri
45
53
  render :text => request.request_uri
@@ -0,0 +1,84 @@
1
+ #include <unistd.h>
2
+ #include "Support.h"
3
+
4
+ namespace Test {
5
+
6
+ string
7
+ readAll(int fd) {
8
+ string result;
9
+ char buf[1024 * 32];
10
+ ssize_t ret;
11
+ while (true) {
12
+ do {
13
+ ret = read(fd, buf, sizeof(buf));
14
+ } while (ret == -1 && errno == EINTR);
15
+ if (ret == 0) {
16
+ break;
17
+ } else if (ret == -1) {
18
+ throw SystemException("Cannot read from socket", errno);
19
+ } else {
20
+ result.append(buf, ret);
21
+ }
22
+ }
23
+ return result;
24
+ }
25
+
26
+ string
27
+ replaceString(const string &str, const string &toFind, const string &replaceWith) {
28
+ string::size_type pos = str.find(toFind);
29
+ if (pos == string::npos) {
30
+ return str;
31
+ } else {
32
+ string result(str);
33
+ return result.replace(pos, toFind.size(), replaceWith);
34
+ }
35
+ }
36
+
37
+ void
38
+ replaceStringInFile(const char *filename, const string &toFind, const string &replaceWith) {
39
+ FILE *f = fopen(filename, "r");
40
+ if (f == NULL) {
41
+ int e = errno;
42
+ string message = "Cannot open file '";
43
+ message.append(filename);
44
+ message.append("' for reading");
45
+ throw FileSystemException(message, e, filename);
46
+ }
47
+ string content(readAll(fileno(f)));
48
+ fclose(f);
49
+
50
+ f = fopen(filename, "w");
51
+ if (f == NULL) {
52
+ int e = errno;
53
+ string message = "Cannot open file '";
54
+ message.append(filename);
55
+ message.append("' for writing");
56
+ throw FileSystemException(message, e, filename);
57
+ }
58
+ content = replaceString(content, toFind, replaceWith);
59
+ fwrite(content.data(), 1, content.size(), f);
60
+ fclose(f);
61
+ }
62
+
63
+ void
64
+ touchFile(const char *filename, time_t timestamp) {
65
+ FILE *f = fopen(filename, "a");
66
+ if (f != NULL) {
67
+ fclose(f);
68
+ } else if (errno != EISDIR) {
69
+ int e = errno;
70
+ string message = "Cannot touch file '";
71
+ message.append(filename);
72
+ message.append("'");
73
+ throw FileSystemException(message, e, filename);
74
+ }
75
+
76
+ if (timestamp != (time_t) -1) {
77
+ struct utimbuf times;
78
+ times.actime = timestamp;
79
+ times.modtime = timestamp;
80
+ utime(filename, &times);
81
+ }
82
+ }
83
+
84
+ } // namespace Test
@@ -6,12 +6,49 @@
6
6
  #include <iostream>
7
7
  #include <string>
8
8
  #include <exception>
9
+ #include <cstdio>
9
10
  #include <cerrno>
10
11
  #include <cstring>
12
+ #include <utime.h>
13
+
14
+ #include "Exceptions.h"
15
+ #include "Utils.h"
11
16
 
12
17
  namespace Test {
13
18
 
14
19
  using namespace std;
20
+ using namespace Passenger;
21
+
22
+ /**
23
+ * Read all data from the given file descriptor until EOF.
24
+ *
25
+ * @throws SystemException
26
+ */
27
+ string readAll(int fd);
28
+
29
+ /**
30
+ * Look for 'toFind' inside 'str', replace it with 'replaceWith' and return the result.
31
+ * Only the first occurence of 'toFind' is replaced.
32
+ */
33
+ string replaceString(const string &str, const string &toFind, const string &replaceWith);
34
+
35
+ /**
36
+ * Look for 'toFind' inside the given file, replace it with 'replaceWith' and write
37
+ * the result back to the file. Only the first occurence of 'toFind' is replaced.
38
+ *
39
+ * @throws FileSystemException
40
+ */
41
+ void replaceStringInFile(const char *filename, const string &toFind, const string &replaceWith);
42
+
43
+ /**
44
+ * Touch the given file: create the file if it doesn't exist, update its
45
+ * timestamp if it does. If the <tt>timestamp</tt> argument is -1, then
46
+ * the current system time will be used, otherwise the given timestamp
47
+ * will be used.
48
+ *
49
+ * @throws FileSystemException
50
+ */
51
+ void touchFile(const char *filename, time_t timestamp = (time_t) - 1);
15
52
 
16
53
  /**
17
54
  * Class which creates a temporary directory of the given name, and deletes
@@ -25,17 +62,38 @@ public:
25
62
  this->name = name;
26
63
  if (mkdir(name.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
27
64
  int e = errno;
28
- cerr << "Cannot create directory '" << name << "': " <<
29
- strerror(e) <<" (" << e << ")" << endl;
30
- throw exception();
65
+ string message = "Cannot create directory '";
66
+ message.append(name);
67
+ message.append("'");
68
+ throw FileSystemException(message, e, name);
31
69
  }
32
70
  }
33
71
 
34
72
  ~TempDir() {
35
- string command("rm -rf \"");
36
- command.append(name);
37
- command.append("\"");
38
- system(command.c_str());
73
+ removeDirTree(name);
74
+ }
75
+ };
76
+
77
+ /**
78
+ * Creates a temporary copy of the given directory. This copy is deleted
79
+ * upon object destruction.
80
+ */
81
+ class TempDirCopy {
82
+ private:
83
+ string dir;
84
+ public:
85
+ TempDirCopy(const string &source, const string &dest) {
86
+ dir = dest;
87
+ removeDirTree(dest);
88
+
89
+ char command[1024];
90
+ snprintf(command, sizeof(command), "cp -pR \"%s\" \"%s\"",
91
+ source.c_str(), dest.c_str());
92
+ system(command);
93
+ }
94
+
95
+ ~TempDirCopy() {
96
+ removeDirTree(dir);
39
97
  }
40
98
  };
41
99
 
@@ -50,7 +108,7 @@ public:
50
108
  this->filename = filename;
51
109
  }
52
110
 
53
- DeleteFileEventually() {
111
+ ~DeleteFileEventually() {
54
112
  unlink(filename.c_str());
55
113
  }
56
114
  };