colouringcode-passenger 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (170) hide show
  1. data/NEWS +129 -0
  2. data/Rakefile +2 -2
  3. data/bin/passenger-install-apache2-module +1 -0
  4. data/bin/passenger-install-nginx-module +4 -2
  5. data/ext/apache2/Hooks.cpp +4 -2
  6. data/ext/common/ApplicationPoolServer.h +1 -1
  7. data/ext/common/ApplicationPoolServerExecutable.cpp +1 -1
  8. data/ext/common/MessageChannel.h +48 -4
  9. data/ext/common/StandardApplicationPool.h +4 -2
  10. data/ext/common/Version.h +1 -1
  11. data/ext/nginx/Configuration.c +1 -1
  12. data/ext/nginx/HttpStatusExtractor.h +1 -0
  13. data/ext/nginx/ScgiRequestParser.h +1 -0
  14. data/ext/oxt/system_calls.cpp +11 -0
  15. data/ext/oxt/system_calls.hpp +2 -1
  16. data/ext/oxt/thread.hpp +97 -1
  17. data/ext/phusion_passenger/native_support.c +30 -1
  18. data/lib/phusion_passenger/constants.rb +1 -1
  19. data/lib/phusion_passenger/dependencies.rb +32 -0
  20. data/lib/phusion_passenger/message_channel.rb +45 -3
  21. data/lib/phusion_passenger/platform_info.rb +1 -1
  22. data/lib/phusion_passenger/rack/application_spawner.rb +10 -4
  23. data/lib/phusion_passenger/rack/request_handler.rb +2 -5
  24. data/lib/phusion_passenger/railz/application_spawner.rb +59 -7
  25. data/lib/phusion_passenger/utils.rb +70 -16
  26. data/{vendor/rack-1.0.0-git/lib/rack → lib/phusion_passenger/utils}/rewindable_input.rb +34 -9
  27. data/test/ApplicationPoolTest.cpp +1 -1
  28. data/test/MessageChannelTest.cpp +9 -1
  29. data/test/stub/message_channel.rb +1 -1
  30. data/test/stub/message_channel_2.rb +1 -1
  31. data/test/stub/message_channel_3.rb +2 -2
  32. metadata +43 -155
  33. data/doc/Architectural overview.html +0 -1
  34. data/doc/rdoc/classes/ConditionVariable.html +0 -194
  35. data/doc/rdoc/classes/Exception.html +0 -120
  36. data/doc/rdoc/classes/GC.html +0 -113
  37. data/doc/rdoc/classes/IO.html +0 -169
  38. data/doc/rdoc/classes/PhusionPassenger.html +0 -238
  39. data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +0 -153
  40. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +0 -517
  41. data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +0 -719
  42. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerAlreadyStarted.html +0 -97
  43. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerError.html +0 -96
  44. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerNotStarted.html +0 -97
  45. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/UnknownMessage.html +0 -96
  46. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +0 -598
  47. data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +0 -140
  48. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +0 -317
  49. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess/Instance.html +0 -138
  50. data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +0 -154
  51. data/doc/rdoc/classes/PhusionPassenger/Application.html +0 -283
  52. data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +0 -172
  53. data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +0 -145
  54. data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +0 -181
  55. data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +0 -141
  56. data/doc/rdoc/classes/PhusionPassenger/InvalidPath.html +0 -92
  57. data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +0 -489
  58. data/doc/rdoc/classes/PhusionPassenger/NativeSupport.html +0 -350
  59. data/doc/rdoc/classes/PhusionPassenger/Rack.html +0 -91
  60. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +0 -188
  61. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +0 -199
  62. data/doc/rdoc/classes/PhusionPassenger/Railz.html +0 -95
  63. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +0 -438
  64. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner/Error.html +0 -98
  65. data/doc/rdoc/classes/PhusionPassenger/Railz/CGIFixed.html +0 -200
  66. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +0 -436
  67. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner/Error.html +0 -98
  68. data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +0 -155
  69. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +0 -402
  70. data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +0 -125
  71. data/doc/rdoc/classes/PhusionPassenger/Utils.html +0 -803
  72. data/doc/rdoc/classes/PhusionPassenger/Utils/PseudoIO.html +0 -169
  73. data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +0 -140
  74. data/doc/rdoc/classes/PhusionPassenger/WSGI.html +0 -89
  75. data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +0 -188
  76. data/doc/rdoc/classes/PlatformInfo.html +0 -866
  77. data/doc/rdoc/classes/RakeExtensions.html +0 -197
  78. data/doc/rdoc/classes/Signal.html +0 -131
  79. data/doc/rdoc/created.rid +0 -1
  80. data/doc/rdoc/files/DEVELOPERS_TXT.html +0 -255
  81. data/doc/rdoc/files/README.html +0 -175
  82. data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +0 -92
  83. data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +0 -129
  84. data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +0 -129
  85. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +0 -126
  86. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +0 -128
  87. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +0 -130
  88. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +0 -122
  89. data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +0 -127
  90. data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +0 -126
  91. data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +0 -122
  92. data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +0 -134
  93. data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +0 -122
  94. data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +0 -122
  95. data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +0 -126
  96. data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +0 -120
  97. data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +0 -122
  98. data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +0 -127
  99. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +0 -133
  100. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +0 -125
  101. data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +0 -140
  102. data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +0 -126
  103. data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +0 -145
  104. data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +0 -125
  105. data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +0 -122
  106. data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +0 -159
  107. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +0 -174
  108. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +0 -129
  109. data/doc/rdoc/files/misc/rake/extensions_rb.html +0 -130
  110. data/doc/rdoc/fr_class_index.html +0 -91
  111. data/doc/rdoc/fr_file_index.html +0 -76
  112. data/doc/rdoc/fr_method_index.html +0 -205
  113. data/doc/rdoc/index.html +0 -26
  114. data/doc/rdoc/rdoc-style.css +0 -187
  115. data/vendor/README +0 -13
  116. data/vendor/README_FOR_PACKAGERS +0 -1
  117. data/vendor/rack-1.0.0-git/COPYING +0 -18
  118. data/vendor/rack-1.0.0-git/KNOWN-ISSUES +0 -18
  119. data/vendor/rack-1.0.0-git/README +0 -353
  120. data/vendor/rack-1.0.0-git/Rakefile +0 -164
  121. data/vendor/rack-1.0.0-git/lib/rack.rb +0 -90
  122. data/vendor/rack-1.0.0-git/lib/rack/adapter/camping.rb +0 -22
  123. data/vendor/rack-1.0.0-git/lib/rack/auth/abstract/handler.rb +0 -37
  124. data/vendor/rack-1.0.0-git/lib/rack/auth/abstract/request.rb +0 -37
  125. data/vendor/rack-1.0.0-git/lib/rack/auth/basic.rb +0 -58
  126. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/md5.rb +0 -124
  127. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/nonce.rb +0 -51
  128. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/params.rb +0 -55
  129. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/request.rb +0 -40
  130. data/vendor/rack-1.0.0-git/lib/rack/auth/openid.rb +0 -487
  131. data/vendor/rack-1.0.0-git/lib/rack/builder.rb +0 -63
  132. data/vendor/rack-1.0.0-git/lib/rack/cascade.rb +0 -41
  133. data/vendor/rack-1.0.0-git/lib/rack/chunked.rb +0 -49
  134. data/vendor/rack-1.0.0-git/lib/rack/commonlogger.rb +0 -52
  135. data/vendor/rack-1.0.0-git/lib/rack/conditionalget.rb +0 -47
  136. data/vendor/rack-1.0.0-git/lib/rack/content_length.rb +0 -29
  137. data/vendor/rack-1.0.0-git/lib/rack/content_type.rb +0 -23
  138. data/vendor/rack-1.0.0-git/lib/rack/deflater.rb +0 -96
  139. data/vendor/rack-1.0.0-git/lib/rack/directory.rb +0 -153
  140. data/vendor/rack-1.0.0-git/lib/rack/file.rb +0 -88
  141. data/vendor/rack-1.0.0-git/lib/rack/handler.rb +0 -69
  142. data/vendor/rack-1.0.0-git/lib/rack/handler/cgi.rb +0 -61
  143. data/vendor/rack-1.0.0-git/lib/rack/handler/evented_mongrel.rb +0 -8
  144. data/vendor/rack-1.0.0-git/lib/rack/handler/fastcgi.rb +0 -88
  145. data/vendor/rack-1.0.0-git/lib/rack/handler/lsws.rb +0 -55
  146. data/vendor/rack-1.0.0-git/lib/rack/handler/mongrel.rb +0 -84
  147. data/vendor/rack-1.0.0-git/lib/rack/handler/scgi.rb +0 -59
  148. data/vendor/rack-1.0.0-git/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  149. data/vendor/rack-1.0.0-git/lib/rack/handler/thin.rb +0 -18
  150. data/vendor/rack-1.0.0-git/lib/rack/handler/webrick.rb +0 -67
  151. data/vendor/rack-1.0.0-git/lib/rack/head.rb +0 -19
  152. data/vendor/rack-1.0.0-git/lib/rack/lint.rb +0 -537
  153. data/vendor/rack-1.0.0-git/lib/rack/lobster.rb +0 -65
  154. data/vendor/rack-1.0.0-git/lib/rack/lock.rb +0 -16
  155. data/vendor/rack-1.0.0-git/lib/rack/methodoverride.rb +0 -27
  156. data/vendor/rack-1.0.0-git/lib/rack/mime.rb +0 -204
  157. data/vendor/rack-1.0.0-git/lib/rack/mock.rb +0 -184
  158. data/vendor/rack-1.0.0-git/lib/rack/recursive.rb +0 -57
  159. data/vendor/rack-1.0.0-git/lib/rack/reloader.rb +0 -106
  160. data/vendor/rack-1.0.0-git/lib/rack/request.rb +0 -248
  161. data/vendor/rack-1.0.0-git/lib/rack/response.rb +0 -183
  162. data/vendor/rack-1.0.0-git/lib/rack/session/abstract/id.rb +0 -142
  163. data/vendor/rack-1.0.0-git/lib/rack/session/cookie.rb +0 -91
  164. data/vendor/rack-1.0.0-git/lib/rack/session/memcache.rb +0 -109
  165. data/vendor/rack-1.0.0-git/lib/rack/session/pool.rb +0 -100
  166. data/vendor/rack-1.0.0-git/lib/rack/showexceptions.rb +0 -349
  167. data/vendor/rack-1.0.0-git/lib/rack/showstatus.rb +0 -106
  168. data/vendor/rack-1.0.0-git/lib/rack/static.rb +0 -38
  169. data/vendor/rack-1.0.0-git/lib/rack/urlmap.rb +0 -55
  170. data/vendor/rack-1.0.0-git/lib/rack/utils.rb +0 -522
data/NEWS CHANGED
@@ -1,3 +1,132 @@
1
+ Release 2.2.12
2
+ --------------
3
+
4
+ * Improved Bundler support.
5
+ Previous versions might not be able to correctly load gems bundled
6
+ by Bundler.
7
+ * Fixed some Ruby 1.9 tempfile.rb compatibility problems.
8
+
9
+
10
+ Release 2.2.11
11
+ --------------
12
+
13
+ * This release fixes a regression that appeared in 2.2.10 which only
14
+ affects Apache. When under high load, Apache might freeze and stop
15
+ responding to requests. It is caused by a race conditions which is
16
+ why it escaped our last release testing.
17
+
18
+ This problem does not affect Nginx; you only have to upgrade if
19
+ you're using Apache.
20
+
21
+ http://groups.google.com/group/phusion-passenger/t/d5bb2f17c8446ea0
22
+
23
+
24
+ Release 2.2.10
25
+ --------------
26
+
27
+ * Fixed some Bundler compatibility problems.
28
+ * Fixed some file descriptor passing problems, which previously
29
+ could lead to mysterious crashes.
30
+ * Fixed some compilation problems on newer GCC versions. Issue #430.
31
+ * Support #size method in rack.input.
32
+
33
+
34
+ Release 2.2.9
35
+ -------------
36
+
37
+ * Fixed compatibility with Rails 3.
38
+ Actually, previous Phusion Passenger releases were already compatible
39
+ with Rails 3, depending on the spawn method that would be invoked. Here's
40
+ the story:
41
+
42
+ Since Phusion Passenger 2.2.8, when the file config.ru exists, Phusion
43
+ Passenger will treat the app as a Rack app, not as a Rails app. This is
44
+ in contrast to earlier versions which gave Rails detection more priority
45
+ than Rack detection. Phusion Passenger loads Rack apps and Rails apps in
46
+ different ways. The Rails loader was not compatible with Rails 3, which
47
+ is what we've fixed in this release.
48
+
49
+ That said, a Rails 3 app would have worked out-of-the-box on Phusion
50
+ Passenger 2.2.8 as well because Rails 3 apps include a config.ru file
51
+ by default, causing Phusion Passenger 2.2.8 to use the Rack loader.
52
+ Earlier versions of Phusion Passenger would just completely bail out
53
+ because they'd use the Rails loader.
54
+
55
+ That said, with 2.2.9 there are still some caveats:
56
+ - Smart spawning (the mechanism with which REE's 33% memory reduction
57
+ is implemented) is *not* supported for Rack apps. This means that if
58
+ you want to utilize smart spawning with Rails 3, then you should
59
+ remove your config.ru file.
60
+ - Rails 3 depends on Rack 1.1.0. You must have Rack 1.1.0 installed as
61
+ a gem, even if you've bundled it with the gem bundler. This is because
62
+ Phusion Passenger itself depends on Rack.
63
+
64
+ Both of these caveats are temporary. We have plans to solve both of these
65
+ properly in the future.
66
+ * What's up with the Gem Bundler?
67
+ There has been some reports that Phusion Passenger is not compatible with
68
+ Yehuda Katz's gem bundler (http://github.com/wycats/bundler). This might
69
+ have been true for an earlier version of the gem bundler, but the latest
70
+ version seems to work fine. Please note that you need to insert the
71
+ following snippet in config/preinitializer.rb, as instructed by the gem
72
+ bundler's README:
73
+
74
+ require "#{RAILS_ROOT}/vendor/gems/environment"
75
+
76
+ The Rails::Boot monkey patching code as posted at
77
+ http://yehudakatz.com/2009/11/03/using-the-new-gem-bundler-today/
78
+ does not seem to be required anymore.
79
+ * Fixed support for ActiveRecord subclasses that connect to another database.
80
+ ActiveRecord subclasses that connect to a database other than the default
81
+ one did not have their connection correctly cleared after forking.
82
+ This can result in weird errors along the lines of "Lost connection to
83
+ MySQL server during query". Issue #429.
84
+ * [Nginx] Fixed PCRE URL.
85
+ passenger-install-nginx-module downloads PCRE 7.8 if PCRE is not already
86
+ installed. However PCRE 7.8 has been removed from their FTP server,
87
+ so we've updated the URL to point to the latest version, 8.0.
88
+
89
+
90
+ Release 2.2.8
91
+ -------------
92
+
93
+ * [Nginx] Fixed some signal handling problems.
94
+ Restarting Nginx on OS X with SIGHUP can sometimes take a long time or
95
+ even fail completely. This is because of some signal handling problems,
96
+ which have now been fixed.
97
+ * [Nginx] Added OpenSSL as dependency.
98
+ OpenSSL is required in order to install Nginx, but this was not checked
99
+ by passenger-install-nginx-module. As a result,
100
+ passenger-install-nginx-module fails on e.g. out-of-the-box Ubuntu
101
+ installations until the user manually installs OpenSSL. Issue #422.
102
+ * [Nginx] Fixed support for internal redirects and subrequests.
103
+ It is now possible to, for example, point X-Accel-Redirects to Phusion
104
+ Passenger-served URLs. Patch contributed by W. Andrew Loe III: issue #433.
105
+ * [Apache] Fixed a GnuTLS compatibility issue.
106
+ mod_gnutls can cause Phusion Passenger to crash because of an unchecked
107
+ NULL pointer. This problem has now been fixed: issue #391.
108
+ * Fixed thread creation issue on Intel Itanium platforms.
109
+ This fixes issue #427.
110
+ * Fixed compilation problems on Linux running on the Renesas SH4 CPU.
111
+ Patch contributed by iwamatsu: issue #428.
112
+ * The Rack library has been unvendored.
113
+ The original reason for vendoring was to work around broken Rails
114
+ applications that explicitly specify Rack as a gem dependency. We've
115
+ found a better workaround that does not require vendoring Rack.
116
+ This also fixes a compatibility problem with Rails 3, because Rails
117
+ 3 depends on a newer Rack version than the one we had vendored.
118
+ Issue #432.
119
+ * Fixed compatibility with Ruby 1.9.1 patchlevel >= 152
120
+ Ruby 1.9.1 patchlevel >= 152 has a bug in its tempfile library. If you've
121
+ seen an error message along the lines of
122
+
123
+ *** Exception IOError in Passenger RequestHandler (closed stream)
124
+
125
+ then this is a Ruby bug at work. This bug has been fixed in Ruby 1.9.2,
126
+ but Ruby 1.9.1 still contains this bug. We've added a workaround so that
127
+ the bug is not triggered with this Ruby version. Issue #432.
128
+
129
+
1
130
  Release 2.2.7
2
131
  -------------
3
132
 
data/Rakefile CHANGED
@@ -648,7 +648,7 @@ spec = Gem::Specification.new do |s|
648
648
  s.homepage = "http://www.colouringcode.com/"
649
649
  s.summary = "Apache module for Ruby on Rails support, custom template support"
650
650
  s.name = "colouringcode-passenger"
651
- s.version = "0.1"
651
+ s.version = "0.2"
652
652
  s.rubyforge_project = "colouringcode-passenger"
653
653
  s.author = "Colouring Code - http://www.colouringcode.com/"
654
654
  s.email = "techystuff@colouringcode.com"
@@ -656,6 +656,7 @@ spec = Gem::Specification.new do |s|
656
656
  s.require_paths = ["lib", "ext"]
657
657
  s.add_dependency 'rake', '>= 0.8.1'
658
658
  s.add_dependency 'fastthread', '>= 1.0.1'
659
+ s.add_dependency 'rack'
659
660
  s.extensions << 'ext/phusion_passenger/extconf.rb'
660
661
  s.files = FileList[
661
662
  'Rakefile',
@@ -702,7 +703,6 @@ spec = Gem::Specification.new do |s|
702
703
  'benchmark/*.{cpp,rb}',
703
704
  'misc/*',
704
705
  'misc/*/*',
705
- 'vendor/**/*',
706
706
  'test/*.{rb,cpp,example}',
707
707
  'test/support/*.{cpp,h,rb}',
708
708
  'test/oxt/*.cpp',
@@ -48,6 +48,7 @@ class Installer < PhusionPassenger::AbstractInstaller
48
48
  Dependencies::Ruby_OpenSSL,
49
49
  Dependencies::RubyGems,
50
50
  Dependencies::Rake,
51
+ Dependencies::Rack,
51
52
  Dependencies::Apache2,
52
53
  Dependencies::Apache2_DevHeaders
53
54
  ]
@@ -45,6 +45,8 @@ class Installer < PhusionPassenger::AbstractInstaller
45
45
  Dependencies::Ruby_OpenSSL,
46
46
  Dependencies::RubyGems,
47
47
  Dependencies::Rake,
48
+ Dependencies::Rack,
49
+ Dependencies::OpenSSL_Dev,
48
50
  Dependencies::Zlib_Dev
49
51
  ]
50
52
  if Dependencies.fastthread_required?
@@ -147,8 +149,8 @@ private
147
149
  new_screen
148
150
  color_puts "<banner>PCRE (required by Nginx) not installed, downloading it...</banner>"
149
151
 
150
- basename = "pcre-7.8.tar.gz"
151
- dirname = "pcre-7.8"
152
+ basename = "pcre-8.00.tar.gz"
153
+ dirname = "pcre-8.00"
152
154
  url = "ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/#{basename}"
153
155
  File.unlink("/tmp/#{basename}") rescue nil
154
156
  FileUtils.rm_rf("/tmp/#{dirname}")
@@ -175,8 +175,10 @@ private:
175
175
  env_arr = apr_table_elts(r->subprocess_env);
176
176
  env_entries = (apr_table_entry_t *) env_arr->elts;
177
177
  for (int i = 0; i < env_arr->nelts; ++i) {
178
- result->push_back(env_entries[i].key);
179
- result->push_back(env_entries[i].val);
178
+ if (env_entries[i].key != NULL && env_entries[i].val != NULL) {
179
+ result->push_back(env_entries[i].key);
180
+ result->push_back(env_entries[i].val);
181
+ }
180
182
  }
181
183
  return result;
182
184
  }
@@ -752,7 +752,7 @@ public:
752
752
  // Write some random data to wake up the server.
753
753
  channel.writeRaw("x", 1);
754
754
 
755
- clientConnection = channel.readFileDescriptor();
755
+ clientConnection = channel.readFileDescriptor(false);
756
756
  return ptr(new Client(clientConnection));
757
757
  } catch (const SystemException &e) {
758
758
  throw SystemException("Could not connect to the ApplicationPool server", e.code());
@@ -701,7 +701,7 @@ Server::start() {
701
701
  }
702
702
 
703
703
  UPDATE_TRACE_POINT();
704
- MessageChannel(serverSocket).writeFileDescriptor(fds[1]);
704
+ MessageChannel(serverSocket).writeFileDescriptor(fds[1], false);
705
705
  syscalls::close(fds[1]);
706
706
 
707
707
  UPDATE_TRACE_POINT();
@@ -319,12 +319,24 @@ public:
319
319
  * descriptor is a Unix socket.
320
320
  *
321
321
  * @param fileDescriptor The file descriptor to pass.
322
+ * @param negotiate See Ruby's MessageChannel#send_io method's comments.
322
323
  * @throws SystemException Something went wrong during file descriptor passing.
323
324
  * @throws boost::thread_interrupted
324
325
  * @pre <tt>fileDescriptor >= 0</tt>
325
326
  * @see readFileDescriptor()
326
327
  */
327
- void writeFileDescriptor(int fileDescriptor) {
328
+ void writeFileDescriptor(int fileDescriptor, bool negotiate = true) {
329
+ // See message_channel.rb for more info about negotiation.
330
+ if (negotiate) {
331
+ vector<string> args;
332
+
333
+ if (!read(args)) {
334
+ throw IOException("Unexpected end of stream encountered while pre-negotiating a file descriptor");
335
+ } else if (args.size() != 1 || args[0] != "pass IO") {
336
+ throw IOException("FD passing pre-negotiation message expected.");
337
+ }
338
+ }
339
+
328
340
  struct msghdr msg;
329
341
  struct iovec vec;
330
342
  char dummy[1];
@@ -368,6 +380,16 @@ public:
368
380
  if (ret == -1) {
369
381
  throw SystemException("Cannot send file descriptor with sendmsg()", errno);
370
382
  }
383
+
384
+ if (negotiate) {
385
+ vector<string> args;
386
+
387
+ if (!read(args)) {
388
+ throw IOException("Unexpected end of stream encountered while post-negotiating a file descriptor");
389
+ } else if (args.size() != 1 || args[0] != "got IO") {
390
+ throw IOException("FD passing post-negotiation message expected.");
391
+ }
392
+ }
371
393
  }
372
394
 
373
395
  /**
@@ -492,6 +514,7 @@ public:
492
514
  * Receive a file descriptor, which had been passed over the underlying
493
515
  * file descriptor.
494
516
  *
517
+ * @param negotiate See Ruby's MessageChannel#send_io method's comments.
495
518
  * @return The passed file descriptor.
496
519
  * @throws SystemException If something went wrong during the
497
520
  * receiving of a file descriptor. Perhaps the underlying
@@ -500,7 +523,12 @@ public:
500
523
  * file descriptor.
501
524
  * @throws boost::thread_interrupted
502
525
  */
503
- int readFileDescriptor() {
526
+ int readFileDescriptor(bool negotiate = true) {
527
+ // See message_channel.rb for more info about negotiation.
528
+ if (negotiate) {
529
+ write("pass IO", NULL);
530
+ }
531
+
504
532
  struct msghdr msg;
505
533
  struct iovec vec;
506
534
  char dummy[1];
@@ -538,16 +566,32 @@ public:
538
566
  }
539
567
 
540
568
  control_header = CMSG_FIRSTHDR(&msg);
569
+ if (control_header == NULL) {
570
+ throw IOException("No valid file descriptor received.");
571
+ }
541
572
  if (control_header->cmsg_len != EXPECTED_CMSG_LEN
542
573
  || control_header->cmsg_level != SOL_SOCKET
543
574
  || control_header->cmsg_type != SCM_RIGHTS) {
544
575
  throw IOException("No valid file descriptor received.");
545
576
  }
577
+
546
578
  #if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)
547
- return control_data.fd;
579
+ int fd = control_data.fd;
548
580
  #else
549
- return *((int *) CMSG_DATA(control_header));
581
+ int fd = *((int *) CMSG_DATA(control_header));
550
582
  #endif
583
+
584
+ if (negotiate) {
585
+ try {
586
+ write("got IO", NULL);
587
+ } catch (...) {
588
+ this_thread::disable_syscall_interruption dsi;
589
+ syscalls::close(fd);
590
+ throw;
591
+ }
592
+ }
593
+
594
+ return fd;
551
595
  }
552
596
 
553
597
  /**
@@ -34,6 +34,7 @@
34
34
 
35
35
  #include <oxt/system_calls.hpp>
36
36
  #include <oxt/backtrace.hpp>
37
+ #include <oxt/thread.hpp>
37
38
 
38
39
  #include <string>
39
40
  #include <sstream>
@@ -242,7 +243,7 @@ private:
242
243
  SpawnManager spawnManager;
243
244
  #endif
244
245
  SharedDataPtr data;
245
- boost::thread *cleanerThread;
246
+ oxt::thread *cleanerThread;
246
247
  bool detached;
247
248
  bool done;
248
249
  unsigned int maxIdleTime;
@@ -632,8 +633,9 @@ public:
632
633
  waitingOnGlobalQueue = 0;
633
634
  maxPerApp = DEFAULT_MAX_INSTANCES_PER_APP;
634
635
  maxIdleTime = DEFAULT_MAX_IDLE_TIME;
635
- cleanerThread = new boost::thread(
636
+ cleanerThread = new oxt::thread(
636
637
  bind(&StandardApplicationPool::cleanerThreadMainLoop, this),
638
+ "ApplicationPool cleaner",
637
639
  CLEANER_THREAD_STACK_SIZE
638
640
  );
639
641
  }
@@ -26,6 +26,6 @@
26
26
  #define _PASSENGER_VERSION_H_
27
27
 
28
28
  /* Don't forget to update lib/phusion_passenger/constants.rb too. */
29
- #define PASSENGER_VERSION "2.2.7"
29
+ #define PASSENGER_VERSION "2.2.12"
30
30
 
31
31
  #endif /* _PASSENGER_VERSION_H */
@@ -194,7 +194,7 @@ passenger_create_loc_conf(ngx_conf_t *cf)
194
194
  DEFINE_VAR_TO_PASS("SCGI", "1");
195
195
  DEFINE_VAR_TO_PASS("QUERY_STRING", "$query_string");
196
196
  DEFINE_VAR_TO_PASS("REQUEST_METHOD", "$request_method");
197
- DEFINE_VAR_TO_PASS("REQUEST_URI", "$request_uri");
197
+ DEFINE_VAR_TO_PASS("REQUEST_URI", "$uri$is_args$args");
198
198
  DEFINE_VAR_TO_PASS("SERVER_PROTOCOL", "$server_protocol");
199
199
  DEFINE_VAR_TO_PASS("SERVER_SOFTWARE", "nginx/$nginx_version");
200
200
  DEFINE_VAR_TO_PASS("REMOTE_ADDR", "$remote_addr");
@@ -26,6 +26,7 @@
26
26
  #include <string>
27
27
  #include <cstdio>
28
28
  #include <cstdlib>
29
+ #include <cstring>
29
30
 
30
31
  namespace Passenger {
31
32
 
@@ -25,6 +25,7 @@
25
25
 
26
26
  #include <string>
27
27
  #include <map>
28
+ #include <cstdlib>
28
29
 
29
30
  #include "StaticString.h"
30
31
 
@@ -42,8 +42,19 @@ interruption_signal_handler(int sig) {
42
42
  void
43
43
  oxt::setup_syscall_interruption_support() {
44
44
  struct sigaction action;
45
+ sigset_t signal_set;
45
46
  int ret;
46
47
 
48
+ /* Very important! The signal mask is inherited across fork()
49
+ * and exec() and we don't know what the parent process did to
50
+ * us. At least on OS X, having a signal mask blocking important
51
+ * signals can lead to stuff like waitpid() malfunction.
52
+ */
53
+ sigemptyset(&signal_set);
54
+ do {
55
+ ret = sigprocmask(SIG_SETMASK, &signal_set, NULL);
56
+ } while (ret == -1 && errno == EINTR);
57
+
47
58
  action.sa_handler = interruption_signal_handler;
48
59
  action.sa_flags = 0;
49
60
  sigemptyset(&action.sa_mask);
@@ -102,7 +102,8 @@ namespace oxt {
102
102
  * Setup system call interruption support.
103
103
  * This function may only be called once. It installs a signal handler
104
104
  * for INTERRUPTION_SIGNAL, so one should not install a different signal
105
- * handler for that signal after calling this function.
105
+ * handler for that signal after calling this function. It also resets
106
+ * the process signal mask.
106
107
  *
107
108
  * @warning
108
109
  * After oxt::setup_syscall_interruption_support() is called, sending a signal
@@ -34,6 +34,9 @@
34
34
  #ifdef OXT_BACKTRACE_IS_ENABLED
35
35
  #include <sstream>
36
36
  #endif
37
+ #include <string>
38
+ #include <list>
39
+ #include <unistd.h>
37
40
  #include <limits.h> // for PTHREAD_STACK_MIN
38
41
 
39
42
  namespace oxt {
@@ -132,17 +135,45 @@ public:
132
135
  set_thread_main_function(boost::bind(thread_main, func, data));
133
136
 
134
137
  unsigned long min_stack_size;
138
+ bool stack_min_size_defined;
139
+ bool round_stack_size;
140
+
135
141
  #ifdef PTHREAD_STACK_MIN
136
142
  // PTHREAD_STACK_MIN may not be a constant macro so we need
137
143
  // to evaluate it dynamically.
138
144
  min_stack_size = PTHREAD_STACK_MIN;
145
+ stack_min_size_defined = true;
139
146
  #else
140
147
  // Assume minimum stack size is 128 KB.
141
148
  min_stack_size = 128 * 1024;
149
+ stack_min_size_defined = false;
142
150
  #endif
143
- if (stack_size < min_stack_size) {
151
+ if (stack_size != 0 && stack_size < min_stack_size) {
144
152
  stack_size = min_stack_size;
153
+ round_stack_size = !stack_min_size_defined;
154
+ } else {
155
+ round_stack_size = true;
156
+ }
157
+
158
+ if (round_stack_size) {
159
+ // Round stack size up to page boundary.
160
+ long page_size;
161
+ #if defined(_SC_PAGESIZE)
162
+ page_size = sysconf(_SC_PAGESIZE);
163
+ #elif defined(_SC_PAGE_SIZE)
164
+ page_size = sysconf(_SC_PAGE_SIZE);
165
+ #elif defined(PAGESIZE)
166
+ page_size = sysconf(PAGESIZE);
167
+ #elif defined(PAGE_SIZE)
168
+ page_size = sysconf(PAGE_SIZE);
169
+ #else
170
+ page_size = getpagesize();
171
+ #endif
172
+ if (stack_size % page_size != 0) {
173
+ stack_size = stack_size - (stack_size % page_size) + page_size;
174
+ }
145
175
  }
176
+
146
177
  start_thread(stack_size);
147
178
  }
148
179
 
@@ -231,6 +262,71 @@ public:
231
262
  done = timed_join(boost::posix_time::millisec(10));
232
263
  }
233
264
  }
265
+
266
+ /**
267
+ * Keep interrupting the thread until it's done, then join it.
268
+ * This method will keep trying for at most <em>timeout</em> milliseconds.
269
+ *
270
+ * @param timeout The maximum number of milliseconds that this method
271
+ * should keep trying.
272
+ * @return True if the thread was successfully joined, false if the
273
+ * timeout has been reached.
274
+ * @throws boost::thread_interrupted The calling thread has been
275
+ * interrupted before we could join this thread.
276
+ */
277
+ bool interrupt_and_join(unsigned int timeout) {
278
+ bool joined = false, timed_out = false;
279
+ boost::posix_time::ptime deadline =
280
+ boost::posix_time::microsec_clock::local_time() +
281
+ boost::posix_time::millisec(timeout);
282
+ while (!joined && !timed_out) {
283
+ interrupt();
284
+ joined = timed_join(boost::posix_time::millisec(10));
285
+ timed_out = !joined && boost::posix_time::microsec_clock::local_time() > deadline;
286
+ }
287
+ return joined;
288
+ }
289
+
290
+ /**
291
+ * Interrupt and join multiple threads in a way that's more efficient than calling
292
+ * interrupt_and_join() on each thread individually. It iterates over all threads,
293
+ * interrupts each one without joining it, then waits until at least one thread
294
+ * is joinable. This is repeated until all threads are joined.
295
+ *
296
+ * @param threads An array of threads to join.
297
+ * @param size The number of elements in <em>threads</em>.
298
+ * @throws boost::thread_interrupted The calling thread has been
299
+ * interrupted before all threads have been joined. Some threads
300
+ * may have been successfully joined while others haven't.
301
+ */
302
+ static void interrupt_and_join_multiple(oxt::thread **threads, unsigned int size) {
303
+ std::list<oxt::thread *> remaining_threads;
304
+ std::list<oxt::thread *>::iterator it, current;
305
+ oxt::thread *thread;
306
+ unsigned int i;
307
+
308
+ for (i = 0; i < size; i++) {
309
+ remaining_threads.push_back(threads[i]);
310
+ }
311
+
312
+ while (!remaining_threads.empty()) {
313
+ for (it = remaining_threads.begin(); it != remaining_threads.end(); it++) {
314
+ thread = *it;
315
+ thread->interrupt();
316
+ }
317
+ for (it = remaining_threads.begin(); it != remaining_threads.end(); it++) {
318
+ thread = *it;
319
+ if (thread->timed_join(boost::posix_time::millisec(0))) {
320
+ current = it;
321
+ it--;
322
+ remaining_threads.erase(current);
323
+ }
324
+ }
325
+ if (!remaining_threads.empty()) {
326
+ syscalls::usleep(10000);
327
+ }
328
+ }
329
+ }
234
330
  };
235
331
 
236
332
  } // namespace oxt