passenger 3.9.2.beta → 4.0.0.rc4

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 (159) hide show
  1. data/.travis.yml +3 -0
  2. data/NEWS +77 -7
  3. data/README.md +3 -11
  4. data/bin/passenger-install-apache2-module +24 -20
  5. data/bin/passenger-install-nginx-module +25 -23
  6. data/build/agents.rb +11 -0
  7. data/build/apache2.rb +9 -5
  8. data/build/basics.rb +37 -30
  9. data/build/common_library.rb +4 -1
  10. data/build/cplusplus_support.rb +5 -5
  11. data/build/cxx_tests.rb +28 -8
  12. data/build/integration_tests.rb +6 -3
  13. data/build/nginx.rb +3 -3
  14. data/build/packaging.rb +95 -57
  15. data/build/ruby_extension.rb +34 -21
  16. data/build/ruby_tests.rb +4 -2
  17. data/build/test_basics.rb +1 -1
  18. data/dev/run_travis.sh +36 -1
  19. data/doc/Users guide Apache.html +425 -308
  20. data/doc/Users guide Apache.idmap.txt +78 -70
  21. data/doc/Users guide Apache.index.sqlite3 +0 -0
  22. data/doc/Users guide Apache.txt +33 -92
  23. data/doc/Users guide Nginx.html +519 -220
  24. data/doc/Users guide Nginx.idmap.txt +78 -60
  25. data/doc/Users guide Nginx.txt +115 -26
  26. data/doc/Users guide Standalone.html +8 -2
  27. data/doc/users_guide_snippets/analysis_and_system_maintenance.txt +1 -7
  28. data/doc/users_guide_snippets/installation.txt +167 -22
  29. data/doc/users_guide_snippets/rackup_specifications.txt +4 -0
  30. data/doc/users_guide_snippets/since_version.txt +1 -0
  31. data/doc/users_guide_snippets/support_information.txt +3 -7
  32. data/doc/users_guide_snippets/tips.txt +0 -24
  33. data/ext/apache2/Configuration.cpp +11 -33
  34. data/ext/apache2/Configuration.hpp +3 -18
  35. data/ext/apache2/DirectoryMapper.h +20 -70
  36. data/ext/apache2/Hooks.cpp +2 -2
  37. data/ext/common/AgentsStarter.cpp +0 -2
  38. data/ext/common/AgentsStarter.h +0 -1
  39. data/ext/common/AgentsStarter.hpp +1 -3
  40. data/ext/common/ApplicationPool2/AppTypes.cpp +74 -0
  41. data/ext/common/ApplicationPool2/AppTypes.h +202 -0
  42. data/ext/common/ApplicationPool2/Common.h +12 -10
  43. data/ext/common/ApplicationPool2/DirectSpawner.h +256 -0
  44. data/ext/common/ApplicationPool2/DummySpawner.h +90 -0
  45. data/ext/common/ApplicationPool2/Group.h +311 -94
  46. data/ext/common/ApplicationPool2/Implementation.cpp +405 -145
  47. data/ext/common/ApplicationPool2/Options.h +24 -26
  48. data/ext/common/ApplicationPool2/PipeWatcher.h +20 -13
  49. data/ext/common/ApplicationPool2/Pool.h +326 -183
  50. data/ext/common/ApplicationPool2/Process.h +205 -55
  51. data/ext/common/ApplicationPool2/README.md +1 -1
  52. data/ext/common/ApplicationPool2/Session.h +21 -10
  53. data/ext/common/ApplicationPool2/SmartSpawner.h +801 -0
  54. data/ext/common/ApplicationPool2/Spawner.h +141 -1149
  55. data/ext/common/ApplicationPool2/SpawnerFactory.h +132 -0
  56. data/ext/common/ApplicationPool2/SuperGroup.h +146 -223
  57. data/ext/common/Constants.h +4 -2
  58. data/ext/common/Exceptions.h +23 -1
  59. data/ext/common/Logging.cpp +17 -6
  60. data/ext/common/Logging.h +37 -7
  61. data/ext/common/ResourceLocator.h +1 -1
  62. data/ext/common/Utils.cpp +49 -1
  63. data/ext/common/Utils.h +13 -4
  64. data/ext/common/{AnsiColorConstants.h → Utils/AnsiColorConstants.h} +0 -0
  65. data/ext/common/{BCrypt.cpp → Utils/BCrypt.cpp} +0 -0
  66. data/ext/common/{BCrypt.h → Utils/BCrypt.h} +0 -0
  67. data/ext/common/{Blowfish.c → Utils/Blowfish.c} +0 -0
  68. data/ext/common/{Blowfish.h → Utils/Blowfish.h} +0 -0
  69. data/ext/common/Utils/CachedFileStat.hpp +27 -25
  70. data/ext/common/Utils/Curl.h +184 -0
  71. data/ext/common/{HttpConstants.h → Utils/HttpConstants.h} +3 -0
  72. data/ext/common/Utils/IOUtils.cpp +6 -2
  73. data/ext/common/{IniFile.h → Utils/IniFile.h} +0 -0
  74. data/ext/common/Utils/LargeFiles.cpp +30 -0
  75. data/ext/common/Utils/LargeFiles.h +40 -0
  76. data/ext/common/Utils/StrIntUtils.cpp +72 -8
  77. data/ext/common/Utils/StrIntUtils.h +24 -2
  78. data/ext/common/Utils/StringMap.h +12 -2
  79. data/ext/common/Utils/VariantMap.h +51 -2
  80. data/ext/common/Utils/jsoncpp.cpp +1 -1
  81. data/ext/common/agents/Base.cpp +147 -11
  82. data/ext/common/agents/HelperAgent/AgentOptions.h +14 -6
  83. data/ext/common/agents/HelperAgent/Main.cpp +79 -19
  84. data/ext/common/agents/HelperAgent/RequestHandler.h +36 -16
  85. data/ext/common/agents/LoggingAgent/LoggingServer.h +3 -5
  86. data/ext/common/agents/LoggingAgent/Main.cpp +2 -4
  87. data/ext/common/agents/LoggingAgent/RemoteSender.h +18 -24
  88. data/ext/common/agents/SpawnPreparer.cpp +7 -0
  89. data/ext/common/agents/Watchdog/Main.cpp +96 -38
  90. data/ext/nginx/Configuration.c +26 -22
  91. data/ext/nginx/Configuration.h +4 -2
  92. data/ext/nginx/ContentHandler.c +23 -52
  93. data/ext/nginx/ContentHandler.h +5 -11
  94. data/ext/nginx/config +10 -3
  95. data/ext/nginx/ngx_http_passenger_module.c +21 -6
  96. data/ext/nginx/ngx_http_passenger_module.h +4 -1
  97. data/ext/oxt/dynamic_thread_group.hpp +9 -1
  98. data/ext/oxt/system_calls.cpp +2 -2
  99. data/ext/ruby/extconf.rb +2 -1
  100. data/helper-scripts/backtrace-sanitizer.rb +2 -0
  101. data/helper-scripts/wsgi-loader.py +54 -21
  102. data/lib/phusion_passenger.rb +5 -3
  103. data/lib/phusion_passenger/abstract_installer.rb +18 -41
  104. data/lib/phusion_passenger/admin_tools/memory_stats.rb +2 -2
  105. data/lib/phusion_passenger/admin_tools/server_instance.rb +2 -2
  106. data/lib/phusion_passenger/common_library.rb +23 -3
  107. data/lib/phusion_passenger/debug_logging.rb +10 -3
  108. data/lib/phusion_passenger/packaging.rb +1 -0
  109. data/lib/phusion_passenger/platform_info.rb +113 -115
  110. data/lib/phusion_passenger/platform_info/compiler.rb +224 -134
  111. data/lib/phusion_passenger/platform_info/cxx_portability.rb +143 -0
  112. data/lib/phusion_passenger/platform_info/depcheck.rb +371 -0
  113. data/lib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +124 -0
  114. data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +97 -0
  115. data/lib/phusion_passenger/platform_info/depcheck_specs/gems.rb +39 -0
  116. data/lib/phusion_passenger/platform_info/depcheck_specs/libs.rb +118 -0
  117. data/lib/phusion_passenger/platform_info/depcheck_specs/ruby.rb +137 -0
  118. data/lib/phusion_passenger/platform_info/depcheck_specs/utilities.rb +15 -0
  119. data/lib/phusion_passenger/platform_info/operating_system.rb +6 -5
  120. data/lib/phusion_passenger/platform_info/ruby.rb +45 -34
  121. data/lib/phusion_passenger/request_handler.rb +35 -22
  122. data/lib/phusion_passenger/request_handler/thread_handler.rb +5 -6
  123. data/lib/phusion_passenger/ruby_core_enhancements.rb +7 -1
  124. data/lib/phusion_passenger/standalone/runtime_installer.rb +43 -34
  125. data/lib/phusion_passenger/utils/robust_interruption.rb +34 -18
  126. data/passenger.gemspec +25 -0
  127. data/resources/templates/standalone/config.erb +3 -1
  128. data/test/config.json.travis +2 -2
  129. data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +37 -5
  130. data/test/cxx/ApplicationPool2/PoolTest.cpp +143 -50
  131. data/test/cxx/ApplicationPool2/ProcessTest.cpp +8 -0
  132. data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +28 -17
  133. data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +31 -26
  134. data/test/cxx/RequestHandlerTest.cpp +17 -1
  135. data/test/cxx/UtilsTest.cpp +84 -10
  136. data/test/integration_tests/apache2_tests.rb +49 -163
  137. data/test/integration_tests/hello_world_wsgi_spec.rb +2 -2
  138. data/test/integration_tests/mycook_spec.rb +1 -1
  139. data/test/integration_tests/nginx_tests.rb +37 -19
  140. data/test/ruby/request_handler_spec.rb +1 -0
  141. data/test/ruby/spec_helper.rb +52 -1
  142. data/test/stub/nginx/nginx.conf.erb +2 -0
  143. data/test/stub/rack/start.rb +5 -0
  144. data/test/stub/rails3.0/Gemfile.lock +30 -30
  145. data/test/stub/rails3.1/Gemfile +1 -1
  146. data/test/stub/rails3.1/Gemfile.lock +3 -3
  147. data/test/stub/rails3.2/Gemfile +1 -1
  148. data/test/stub/rails3.2/Gemfile.lock +4 -4
  149. data/test/stub/rails_apps/2.3/mycook/app/controllers/welcome_controller.rb +1 -1
  150. data/test/stub/rails_apps/2.3/mycook/app/helpers/recipes_helper.rb +2 -0
  151. data/test/stub/rails_apps/2.3/mycook/app/helpers/test_helper.rb +2 -0
  152. data/test/stub/rails_apps/2.3/mycook/app/helpers/uploads_helper.rb +2 -0
  153. data/test/stub/rails_apps/2.3/mycook/app/helpers/welcome_helper.rb +2 -0
  154. data/test/support/nginx_controller.rb +2 -1
  155. metadata +160 -156
  156. data/build/gempackagetask.rb +0 -99
  157. data/build/packagetask.rb +0 -186
  158. data/ext/common/StringListCreator.h +0 -83
  159. data/lib/phusion_passenger/dependencies.rb +0 -657
@@ -431,50 +431,63 @@ private
431
431
  initialization_state_mutex = Mutex.new
432
432
  initialization_state_cond = ConditionVariable.new
433
433
  initialization_state = {}
434
+ set_initialization_state = lambda do |value|
435
+ initialization_state_mutex.synchronize do
436
+ initialization_state[Thread.current] = value
437
+ initialization_state_cond.signal
438
+ end
439
+ end
440
+ set_initialization_state_to_true = lambda do
441
+ set_initialization_state.call(true)
442
+ end
434
443
 
435
444
  # Actually start all the threads.
436
445
  thread_handler = @thread_handler
446
+ expected_nthreads = 0
447
+
437
448
  @threads_mutex.synchronize do
438
449
  @concurrency.times do |i|
439
450
  thread = Thread.new(i) do |number|
440
451
  Thread.current.abort_on_exception = true
441
- begin
442
- Thread.current[:name] = "Worker #{number + 1}"
443
- handler = thread_handler.new(self, main_socket_options)
444
- handler.install
445
- initialization_state_mutex.synchronize do
446
- initialization_state[Thread.current] = true
447
- initialization_state_cond.signal
448
- end
449
- handler.main_loop
450
- ensure
451
- initialization_state_mutex.synchronize do
452
- initialization_state[Thread.current] = false
453
- initialization_state_cond.signal
452
+ RobustInterruption.install
453
+ RobustInterruption.disable_interruptions do
454
+ begin
455
+ Thread.current[:name] = "Worker #{number + 1}"
456
+ handler = thread_handler.new(self, main_socket_options)
457
+ handler.install
458
+ handler.main_loop(set_initialization_state_to_true)
459
+ ensure
460
+ set_initialization_state.call(false)
461
+ unregister_current_thread
454
462
  end
455
- unregister_current_thread
456
463
  end
457
464
  end
458
465
  @threads << thread
466
+ expected_nthreads += 1
459
467
  end
460
468
 
461
469
  thread = Thread.new do
462
470
  Thread.current.abort_on_exception = true
463
- begin
464
- Thread.current[:name] = "HTTP helper worker"
465
- handler = thread_handler.new(self, http_socket_options)
466
- handler.install
467
- handler.main_loop
468
- ensure
469
- unregister_current_thread
471
+ RobustInterruption.install
472
+ RobustInterruption.disable_interruptions do
473
+ begin
474
+ Thread.current[:name] = "HTTP helper worker"
475
+ handler = thread_handler.new(self, http_socket_options)
476
+ handler.install
477
+ handler.main_loop(set_initialization_state_to_true)
478
+ ensure
479
+ set_initialization_state.call(false)
480
+ unregister_current_thread
481
+ end
470
482
  end
471
483
  end
472
484
  @threads << thread
485
+ expected_nthreads += 1
473
486
  end
474
487
 
475
488
  # Wait until all threads have finished starting.
476
489
  initialization_state_mutex.synchronize do
477
- while initialization_state.size != @concurrency
490
+ while initialization_state.size != expected_nthreads
478
491
  initialization_state_cond.wait(initialization_state_mutex)
479
492
  end
480
493
  end
@@ -91,18 +91,17 @@ class ThreadHandler
91
91
  PhusionPassenger.call_event(:starting_request_handler_thread)
92
92
  end
93
93
 
94
- def main_loop
94
+ def main_loop(finish_callback)
95
95
  socket_wrapper = Utils::UnseekableSocket.new
96
96
  channel = MessageChannel.new
97
97
  buffer = ''
98
98
  buffer.force_encoding('binary') if buffer.respond_to?(:force_encoding)
99
99
 
100
100
  begin
101
- disable_interruptions do
102
- while !Utils::RobustInterruption.interrupted?
103
- hijacked = accept_and_process_next_request(socket_wrapper, channel, buffer)
104
- socket_wrapper = Utils::UnseekableSocket.new if hijacked
105
- end
101
+ finish_callback.call
102
+ while !Utils::RobustInterruption.interrupted?
103
+ hijacked = accept_and_process_next_request(socket_wrapper, channel, buffer)
104
+ socket_wrapper = Utils::UnseekableSocket.new if hijacked
106
105
  end
107
106
  rescue Utils::RobustInterruption::Interrupted
108
107
  # Do nothing.
@@ -26,7 +26,13 @@ require 'rubygems'
26
26
  require 'socket'
27
27
  require 'thread'
28
28
  if (!defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby") && RUBY_VERSION < "1.8.7"
29
- require 'fastthread'
29
+ begin
30
+ require 'fastthread'
31
+ rescue LoadError
32
+ abort "You are using a very old Ruby version. You must install " +
33
+ "the 'fastthread' gem to fix some bugs in the Ruby threading system: " +
34
+ "gem install fastthread"
35
+ end
30
36
  end
31
37
  require 'phusion_passenger/native_support'
32
38
 
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
  #
3
3
  # Phusion Passenger - https://www.phusionpassenger.com/
4
- # Copyright (c) 2010, 2011, 2012 Phusion
4
+ # Copyright (c) 2010-2013 Phusion
5
5
  #
6
6
  # "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
7
7
  #
@@ -26,7 +26,6 @@ require 'fileutils'
26
26
  require 'phusion_passenger'
27
27
  require 'phusion_passenger/abstract_installer'
28
28
  require 'phusion_passenger/packaging'
29
- require 'phusion_passenger/dependencies'
30
29
  require 'phusion_passenger/common_library'
31
30
  require 'phusion_passenger/platform_info/ruby'
32
31
  require 'phusion_passenger/platform_info/binary_compatibility'
@@ -50,7 +49,7 @@ module Standalone
50
49
  #
51
50
  # If 'targets' contains :nginx, then you must also specify these options:
52
51
  # - nginx_dir: Nginx will be installed into this directory.
53
- # - support_dir: See below.
52
+ # - support_dir: Path to the Phusion Passenger support binary files.
54
53
  # - nginx_version (optional): The Nginx version to download. If not given then a
55
54
  # hardcoded version number will be used.
56
55
  # - nginx_tarball (optional): The location to the Nginx tarball. This tarball *must*
@@ -84,25 +83,30 @@ class RuntimeInstaller < AbstractInstaller
84
83
 
85
84
  protected
86
85
  def dependencies
87
- result = [
88
- Dependencies::GCC,
89
- Dependencies::GnuMake,
90
- Dependencies::DownloadTool,
91
- Dependencies::Ruby_DevHeaders,
92
- Dependencies::Ruby_OpenSSL,
93
- Dependencies::RubyGems,
94
- Dependencies::Rake,
95
- Dependencies::Rack,
96
- Dependencies::Curl_Dev,
97
- Dependencies::OpenSSL_Dev,
98
- Dependencies::Zlib_Dev,
99
- Dependencies::PCRE_Dev,
100
- Dependencies::Daemon_Controller,
86
+ specs = [
87
+ 'depcheck_specs/compiler_toolchain',
88
+ 'depcheck_specs/ruby',
89
+ 'depcheck_specs/gems',
90
+ 'depcheck_specs/libs',
91
+ 'depcheck_specs/utilities'
101
92
  ]
102
- if Dependencies.fastthread_required?
103
- result << Dependencies::FastThread
104
- end
105
- return result
93
+ ids = [
94
+ 'gcc',
95
+ 'g++',
96
+ 'gmake',
97
+ 'download-tool',
98
+ 'ruby-dev',
99
+ 'ruby-openssl',
100
+ 'rubygems',
101
+ 'rake',
102
+ 'rack',
103
+ 'libcurl-dev',
104
+ 'openssl-dev',
105
+ 'zlib-dev',
106
+ 'pcre-dev',
107
+ 'daemon_controller >= 1.1.0'
108
+ ]
109
+ return [specs, ids]
106
110
  end
107
111
 
108
112
  def users_guide
@@ -291,7 +295,7 @@ private
291
295
 
292
296
  def extract_tarball(filename)
293
297
  File.open(filename, 'rb') do |f|
294
- IO.popen("tar xzf -", "w") do |io|
298
+ IO.popen("tar xzf -", "wb") do |io|
295
299
  buffer = ''
296
300
  buffer = buffer.force_encoding('binary') if buffer.respond_to?(:force_encoding)
297
301
  total_size = File.size(filename)
@@ -494,15 +498,16 @@ private
494
498
  end
495
499
 
496
500
  system "rm -rf '#{@support_dir}'/{*.o,*.dSYM,libboost_oxt}"
497
- system "rm -rf '#{@support_dir}'/*/{*.o,*.lo,*.h,*.log,Makefile,libtool,stamp-h1,config.status,.deps}"
501
+ system "rm -rf '#{@support_dir}'/*/{*.lo,*.h,*.log,Makefile,libtool,stamp-h1,config.status,.deps}"
502
+ system "rm -rf '#{@support_dir}'/{libeio,libev}/*.o"
498
503
 
499
504
  # Retain only the object files that are needed for linking the Phusion Passenger module into Nginx.
500
505
  nginx_libs = COMMON_LIBRARY.
501
506
  only(*NGINX_LIBS_SELECTOR).
502
507
  set_output_dir("#{@support_dir}/libpassenger_common").
503
508
  link_objects
504
- (Dir["#{@support_dir}/libpassenger_common/**/*"] - nginx_libs).each do |filename|
505
- if File.file?(filename)
509
+ Dir["#{@support_dir}/libpassenger_common/**/*"].each do |filename|
510
+ if !nginx_libs.include?(filename) && File.file?(filename)
506
511
  File.unlink(filename)
507
512
  end
508
513
  end
@@ -513,6 +518,19 @@ private
513
518
  def install_nginx_from_source(source_dir)
514
519
  require 'phusion_passenger/platform_info/compiler'
515
520
  Dir.chdir(source_dir) do
521
+ shell = PlatformInfo.find_command('bash') || "sh"
522
+ command = ""
523
+ if @targets.include?(:support_binaries)
524
+ if ENV['PASSENGER_DEBUG'] && !ENV['PASSENGER_DEBUG'].empty?
525
+ output_dir = "#{PhusionPassenger.source_root}/libout/common/libpassenger_common"
526
+ else
527
+ output_dir = "#{@support_dir}/libpassenger_common"
528
+ end
529
+ nginx_libs = COMMON_LIBRARY.only(*NGINX_LIBS_SELECTOR).
530
+ set_output_dir(output_dir).
531
+ link_objects_as_string
532
+ command << "env PASSENGER_LIBS='#{nginx_libs} #{output_dir}/../libboost_oxt.a' "
533
+ end
516
534
  # RPM thinks it's being smart by scanning binaries for
517
535
  # paths and refusing to create package if it detects any
518
536
  # hardcoded thats that point to /usr or other important
@@ -521,15 +539,6 @@ private
521
539
  # we pass it its resource locations during runtime, so
522
540
  # work around the problem by configure Nginx with prefix
523
541
  # /tmp.
524
- shell = PlatformInfo.find_command('bash') || "sh"
525
- command = ""
526
- if @targets.include?(:support_binaries)
527
- nginx_libs = COMMON_LIBRARY.
528
- only(*NGINX_LIBS_SELECTOR).
529
- set_output_dir("#{PhusionPassenger.source_root}/libout/common/libpassenger_common").
530
- link_objects_as_string
531
- command << "env PASSENGER_LIBS='#{nginx_libs} #{@support_dir}/libboost_oxt.a' "
532
- end
533
542
  command << "#{shell} ./configure --prefix=/tmp " <<
534
543
  "--with-cc-opt='-Wno-error' " <<
535
544
  "--without-http_fastcgi_module " <<
@@ -39,7 +39,7 @@ module RobustInterruption
39
39
  end
40
40
 
41
41
  def pop_interruption_flag
42
- raise "BUG - cannot pop interruption flag in this state" if @interruption_flags.size <= 1
42
+ Kernel.raise "BUG - cannot pop interruption flag in this state" if @interruption_flags.size <= 1
43
43
  @interruption_flags.pop
44
44
  end
45
45
  end
@@ -52,27 +52,43 @@ module RobustInterruption
52
52
  RobustInterruption.install
53
53
  end
54
54
 
55
+ def installed?(thread = Thread.current)
56
+ return !!thread[:robust_interruption]
57
+ end
58
+ module_function :installed?
59
+
55
60
  def interrupted?(thread = Thread.current)
56
- data = thread[:robust_interruption]
57
- return data && data.interrupted?
61
+ if data = thread[:robust_interruption]
62
+ return data.interrupted?
63
+ else
64
+ Kernel.raise "RobustThreadInterruption not installed for #{thread}"
65
+ end
58
66
  end
59
67
  module_function :interrupted?
60
68
 
61
69
  def self.raise(thread, exception = Interrupted)
62
- RobustInterruption.disable_interruptions do
63
- data = thread[:robust_interruption]
64
- if data
65
- data.interrupted = true
66
- if data.try_lock
67
- begin
68
- thread.raise(exception)
69
- ensure
70
- data.unlock
71
- end
70
+ if installed?
71
+ RobustInterruption.disable_interruptions(Thread.current) do
72
+ _raise(thread, exception)
73
+ end
74
+ else
75
+ _raise(thread, exception)
76
+ end
77
+ end
78
+
79
+ def self._raise(thread, exception)
80
+ data = thread[:robust_interruption]
81
+ if data
82
+ data.interrupted = true
83
+ if data.try_lock
84
+ begin
85
+ thread.raise(exception)
86
+ ensure
87
+ data.unlock
72
88
  end
73
- else
74
- thread.raise(exception)
75
89
  end
90
+ else
91
+ Kernel.raise "RobustThreadInterruption not installed for #{thread}"
76
92
  end
77
93
  end
78
94
 
@@ -89,7 +105,7 @@ module RobustInterruption
89
105
  data.unlock if was_interruptable
90
106
  end
91
107
  else
92
- yield
108
+ Kernel.raise "RobustThreadInterruption not installed for #{thread}"
93
109
  end
94
110
  end
95
111
  module_function :disable_interruptions
@@ -107,7 +123,7 @@ module RobustInterruption
107
123
  data.pop_interruption_flag
108
124
  end
109
125
  else
110
- yield
126
+ Kernel.raise "RobustThreadInterruption not installed for #{thread}"
111
127
  end
112
128
  end
113
129
  module_function :enable_interruptions
@@ -128,7 +144,7 @@ module RobustInterruption
128
144
  end
129
145
  end
130
146
  else
131
- yield
147
+ Kernel.raise "RobustThreadInterruption not installed for #{thread}"
132
148
  end
133
149
  end
134
150
  module_function :restore_interruptions
@@ -0,0 +1,25 @@
1
+ source_root = File.expand_path(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift("#{source_root}/lib")
3
+ require 'phusion_passenger'
4
+ PhusionPassenger.locate_directories
5
+ require 'phusion_passenger/packaging'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.platform = Gem::Platform::RUBY
9
+ s.homepage = "https://www.phusionpassenger.com/"
10
+ s.summary = "Easy and robust Ruby web application deployment"
11
+ s.name = PhusionPassenger::PACKAGE_NAME
12
+ s.version = PhusionPassenger::VERSION_STRING
13
+ s.rubyforge_project = "passenger"
14
+ s.author = "Phusion - http://www.phusion.nl/"
15
+ s.email = "info@phusion.nl"
16
+ s.require_paths = ["lib"]
17
+ s.add_dependency 'rake', '>= 0.8.1'
18
+ s.add_dependency 'daemon_controller', '>= 1.1.0'
19
+ s.add_dependency 'rack'
20
+ s.files = Dir[*PhusionPassenger::Packaging::GLOB] -
21
+ Dir[*PhusionPassenger::Packaging::EXCLUDE_GLOB]
22
+ s.executables = PhusionPassenger::Packaging::USER_EXECUTABLES +
23
+ PhusionPassenger::Packaging::SUPER_USER_EXECUTABLES
24
+ s.description = "Easy and robust Ruby web application deployment."
25
+ end
@@ -56,9 +56,10 @@ http {
56
56
  <% end %>
57
57
 
58
58
  default_type application/octet-stream;
59
- client_max_body_size 50m;
59
+ client_max_body_size 1024m;
60
60
  access_log off;
61
61
  keepalive_timeout 60;
62
+ underscores_in_headers on;
62
63
  gzip on;
63
64
  gzip_comp_level 3;
64
65
  gzip_min_length 150;
@@ -85,6 +86,7 @@ http {
85
86
  listen <%= nginx_listen_address(app) %>;
86
87
  server_name <%= app[:server_names].join(' ') %>;
87
88
  root '<%= app[:root] %>/public';
89
+ passenger_app_root '<%= app[:root] %>';
88
90
  passenger_enabled on;
89
91
  rails_env <%= app[:env] %>;
90
92
  passenger_spawn_method <%= app[:spawn_method] %>;
@@ -9,7 +9,7 @@
9
9
  "nonexistant_user": "xxxxxxxxxxxxxxxxxxx",
10
10
  "nonexistant_group": "xxxxxxxxxxxxxxxxxxx",
11
11
  "nonexistant_uid": 9999,
12
- "nonexistant_gid": 9999
12
+ "nonexistant_gid": 9999,
13
13
 
14
- // nginx: /usr/local/sbin/nginx
14
+ "nginx": "/tmp/nginx/sbin/nginx"
15
15
  }
@@ -1,5 +1,5 @@
1
1
  #include <TestSupport.h>
2
- #include <ApplicationPool2/Spawner.h>
2
+ #include <ApplicationPool2/DirectSpawner.h>
3
3
  #include <Utils/json.h>
4
4
  #include <fcntl.h>
5
5
 
@@ -11,14 +11,24 @@ namespace tut {
11
11
  ServerInstanceDirPtr serverInstanceDir;
12
12
  ServerInstanceDir::GenerationPtr generation;
13
13
  BackgroundEventLoop bg;
14
+ ProcessPtr process;
15
+ PipeWatcher::DataCallback gatherOutput;
16
+ string gatheredOutput;
17
+ boost::mutex gatheredOutputSyncher;
14
18
 
15
19
  ApplicationPool2_DirectSpawnerTest() {
16
20
  createServerInstanceDirAndGeneration(serverInstanceDir, generation);
17
21
  bg.start();
22
+ PipeWatcher::onData = PipeWatcher::DataCallback();
23
+ gatherOutput = boost::bind(&ApplicationPool2_DirectSpawnerTest::_gatherOutput, this, _1, _2);
24
+ setLogLevel(LVL_ERROR); // TODO: change to LVL_WARN
18
25
  }
19
26
 
20
27
  ~ApplicationPool2_DirectSpawnerTest() {
28
+ setLogLevel(DEFAULT_LOG_LEVEL);
21
29
  unlink("stub/wsgi/passenger_wsgi.pyc");
30
+ Process::maybeShutdown(process);
31
+ PipeWatcher::onData = PipeWatcher::DataCallback();
22
32
  }
23
33
 
24
34
  shared_ptr<DirectSpawner> createSpawner(const Options &options) {
@@ -32,6 +42,11 @@ namespace tut {
32
42
  options.loadShellEnvvars = false;
33
43
  return options;
34
44
  }
45
+
46
+ void _gatherOutput(const char *data, unsigned int size) {
47
+ lock_guard<boost::mutex> l(gatheredOutputSyncher);
48
+ gatheredOutput.append(data, size);
49
+ }
35
50
  };
36
51
 
37
52
  DEFINE_TEST_GROUP_WITH_LIMIT(ApplicationPool2_DirectSpawnerTest, 90);
@@ -57,8 +72,7 @@ namespace tut {
57
72
  } catch (const SpawnException &e) {
58
73
  ensure_equals(e.getErrorKind(),
59
74
  SpawnException::APP_STARTUP_TIMEOUT);
60
- ensure_equals(e.getErrorPage(),
61
- "hello world\n");
75
+ ensure(e.getErrorPage().find("hello world\n") != string::npos);
62
76
  }
63
77
  }
64
78
 
@@ -80,8 +94,26 @@ namespace tut {
80
94
  } catch (const SpawnException &e) {
81
95
  ensure_equals(e.getErrorKind(),
82
96
  SpawnException::APP_STARTUP_PROTOCOL_ERROR);
83
- ensure_equals(e.getErrorPage(),
84
- "hello world\n");
97
+ ensure(e.getErrorPage().find("hello world\n") != string::npos);
85
98
  }
86
99
  }
100
+
101
+ TEST_METHOD(82) {
102
+ SHOW_EXCEPTION_BACKTRACE(
103
+ // Test that everything works correctly if the app re-execs() itself.
104
+ // https://code.google.com/p/phusion-passenger/issues/detail?id=842#c19
105
+ Options options = createOptions();
106
+ options.appRoot = "stub/rack";
107
+ options.startCommand = "ruby\1" "start.rb\1" "--execself";
108
+ options.startupFile = "start.rb";
109
+ SpawnerPtr spawner = createSpawner(options);
110
+ process = spawner->spawn(options);
111
+ ensure_equals(process->sockets->size(), 1u);
112
+
113
+ Connection conn = process->sockets->front().checkoutConnection();
114
+ ScopeGuard guard(boost::bind(checkin, process, &conn));
115
+ writeExact(conn.fd, "ping\n");
116
+ ensure_equals(readAll(conn.fd), "pong\n");
117
+ );
118
+ }
87
119
  }