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
@@ -24,276 +24,276 @@
24
24
  PhusionPassenger.require_passenger_lib 'utils' # So that we can know whether #writev is supported.
25
25
 
26
26
  module PhusionPassenger
27
- module Utils
28
-
29
- # Some frameworks (e.g. Merb) call `seek` and `rewind` on the input stream
30
- # if it responds to these methods. In case of Phusion Passenger, the input
31
- # stream is a socket, and altough socket objects respond to `seek` and
32
- # `rewind`, calling these methods will raise an exception. We don't want
33
- # this to happen so in AbstractRequestHandler we wrap the client socket
34
- # into an UnseekableSocket wrapper, which doesn't respond to these methods.
35
- #
36
- # We used to dynamically undef `seek` and `rewind` on sockets, but this
37
- # blows the Ruby interpreter's method cache and made things slower.
38
- # Wrapping a socket is faster despite extra method calls.
39
- #
40
- # Furthermore, all exceptions originating from the wrapped socket will
41
- # be annotated. One can check whether a certain exception originates
42
- # from the wrapped socket by calling #source_of_exception?
43
- class UnseekableSocket
44
- def self.wrap(socket)
45
- return new.wrap(socket)
46
- end
47
-
48
- def wrap(socket)
49
- # Some people report that sometimes their Ruby (MRI/REE)
50
- # processes get stuck with 100% CPU usage. Upon further
51
- # inspection with strace, it turns out that these Ruby
52
- # processes are continuously calling lseek() on a socket,
53
- # which of course returns ESPIPE as error. gdb reveals
54
- # lseek() is called by fwrite(), which in turn is called
55
- # by rb_fwrite(). The affected socket is the
56
- # AbstractRequestHandler client socket.
57
- #
58
- # I inspected the MRI source code and didn't find
59
- # anything that would explain this behavior. This makes
60
- # me think that it's a glibc bug, but that's very
61
- # unlikely.
62
- #
63
- # The rb_fwrite() implementation takes an entirely
64
- # different code path if I set 'sync' to true: it will
65
- # skip fwrite() and use write() instead. So here we set
66
- # 'sync' to true in the hope that this will work around
67
- # the problem.
68
- socket.sync = true
69
-
70
- # There's no need to set the encoding for Ruby 1.9 because
71
- # abstract_request_handler.rb is tagged with 'encoding: binary'.
72
-
73
- @socket = socket
74
-
75
- return self
76
- end
77
-
78
- # Don't allow disabling of sync.
79
- def sync=(value)
80
- end
81
-
82
- # Socket is sync'ed so flushing shouldn't do anything.
83
- def flush
84
- end
85
-
86
- # Already set to binary mode.
87
- def binmode
88
- end
89
-
90
- # This makes select() work.
91
- def to_io
92
- @socket
93
- end
94
-
95
- def simulate_eof!
96
- @simulate_eof = true
97
- end
98
-
99
- def stop_simulating_eof!
100
- @simulate_eof = false
101
- end
102
-
103
- def fileno
104
- @socket.fileno
105
- end
106
-
107
- def addr
108
- @socket.addr
109
- rescue => e
110
- raise annotate(e)
111
- end
112
-
113
- def write(string)
114
- @socket.write(string)
115
- rescue => e
116
- raise annotate(e)
117
- end
118
-
119
- def write_nonblock(string)
120
- @socket.write_nonblock(string)
121
- rescue => e
122
- raise annotate(e)
123
- end
124
-
125
- def writev(components)
126
- @socket.writev(components)
127
- rescue => e
128
- raise annotate(e)
129
- end if IO.method_defined?(:writev)
130
-
131
- def writev2(components, components2)
132
- @socket.writev2(components, components2)
133
- rescue => e
134
- raise annotate(e)
135
- end if IO.method_defined?(:writev2)
136
-
137
- def writev3(components, components2, components3)
138
- @socket.writev3(components, components2, components3)
139
- rescue => e
140
- raise annotate(e)
141
- end if IO.method_defined?(:writev3)
142
-
143
- def send(*args)
144
- @socket.send(*args)
145
- rescue => e
146
- raise annotate(e)
147
- end
148
-
149
- def sendmsg(*args)
150
- @socket.sendmsg(*args)
151
- rescue => e
152
- raise annotate(e)
153
- end
154
-
155
- def sendmsg_nonblock(*args)
156
- @socket.sendmsg_nonblock(*args)
157
- rescue => e
158
- raise annotate(e)
159
- end
160
-
161
- def puts(*args)
162
- @socket.puts(*args)
163
- rescue => e
164
- raise annotate(e)
165
- end
166
-
167
- def gets
168
- return nil if @simulate_eof
169
- @socket.gets
170
- rescue => e
171
- raise annotate(e)
172
- end
173
-
174
- def read(*args)
175
- if @simulate_eof
176
- length, buffer = args
177
- if buffer
178
- buffer.replace(binary_string(""))
179
- else
180
- buffer = binary_string("")
181
- end
182
- if length
183
- return nil
184
- else
185
- return buffer
186
- end
187
- end
188
- @socket.read(*args)
189
- rescue => e
190
- raise annotate(e)
191
- end
192
-
193
- def read_nonblock(*args)
194
- raise EOFError, "end of file reached" if @simulate_eof
195
- @socket.read_nonblock(*args)
196
- rescue => e
197
- raise annotate(e)
198
- end
199
-
200
- def readpartial(*args)
201
- raise EOFError, "end of file reached" if @simulate_eof
202
- @socket.readpartial(*args)
203
- rescue => e
204
- raise annotate(e)
205
- end
206
-
207
- def readline
208
- raise EOFError, "end of file reached" if @simulate_eof
209
- @socket.readline
210
- rescue => e
211
- raise annotate(e)
212
- end
213
-
214
- def recv(*args)
215
- raise EOFError, "end of file reached" if @simulate_eof
216
- @socket.recv(*args)
217
- rescue => e
218
- raise annotate(e)
219
- end
220
-
221
- def recvfrom(*args)
222
- raise EOFError, "end of file reached" if @simulate_eof
223
- @socket.recvfrom(*args)
224
- rescue => e
225
- raise annotate(e)
226
- end
227
-
228
- def recvfrom_nonblock(*args)
229
- raise EOFError, "end of file reached" if @simulate_eof
230
- @socket.recvfrom_nonblock(*args)
231
- rescue => e
232
- raise annotate(e)
233
- end
234
-
235
- def each(&block)
236
- return if @simulate_eof
237
- @socket.each(&block)
238
- rescue => e
239
- raise annotate(e)
240
- end
241
-
242
- def eof?
243
- return true if @simulate_eof
244
- @socket.eof?
245
- rescue => e
246
- raise annotate(e)
247
- end
248
-
249
- def closed?
250
- @socket.closed?
251
- rescue => e
252
- raise annotate(e)
253
- end
254
-
255
- def close
256
- @socket.close
257
- rescue => e
258
- raise annotate(e)
259
- end
260
-
261
- def close_read
262
- @socket.close_read
263
- rescue => e
264
- raise annotate(e)
265
- end
266
-
267
- def close_write
268
- @socket.close_write
269
- rescue => e
270
- raise annotate(e)
271
- end
272
-
273
- def source_of_exception?(exception)
274
- return exception.instance_variable_get(:"@from_unseekable_socket") == @socket.object_id
275
- end
276
-
277
- private
278
- def annotate(exception)
279
- exception.instance_variable_set(:"@from_unseekable_socket", @socket.object_id)
280
- return exception
281
- end
282
-
283
- def raise_error_because_activity_disallowed!
284
- raise IOError, "It is not possible to read or write from the client socket because the current."
285
- end
286
-
287
- if ''.respond_to?(:force_encoding)
288
- def binary_string(str)
289
- return ''.force_encoding('binary')
290
- end
291
- else
292
- def binary_string(str)
293
- return ''
294
- end
295
- end
296
- end
297
-
298
- end # module Utils
27
+ module Utils
28
+
29
+ # Some frameworks (e.g. Merb) call `seek` and `rewind` on the input stream
30
+ # if it responds to these methods. In case of Phusion Passenger, the input
31
+ # stream is a socket, and altough socket objects respond to `seek` and
32
+ # `rewind`, calling these methods will raise an exception. We don't want
33
+ # this to happen so in AbstractRequestHandler we wrap the client socket
34
+ # into an UnseekableSocket wrapper, which doesn't respond to these methods.
35
+ #
36
+ # We used to dynamically undef `seek` and `rewind` on sockets, but this
37
+ # blows the Ruby interpreter's method cache and made things slower.
38
+ # Wrapping a socket is faster despite extra method calls.
39
+ #
40
+ # Furthermore, all exceptions originating from the wrapped socket will
41
+ # be annotated. One can check whether a certain exception originates
42
+ # from the wrapped socket by calling #source_of_exception?
43
+ class UnseekableSocket
44
+ def self.wrap(socket)
45
+ return new.wrap(socket)
46
+ end
47
+
48
+ def wrap(socket)
49
+ # Some people report that sometimes their Ruby (MRI/REE)
50
+ # processes get stuck with 100% CPU usage. Upon further
51
+ # inspection with strace, it turns out that these Ruby
52
+ # processes are continuously calling lseek() on a socket,
53
+ # which of course returns ESPIPE as error. gdb reveals
54
+ # lseek() is called by fwrite(), which in turn is called
55
+ # by rb_fwrite(). The affected socket is the
56
+ # AbstractRequestHandler client socket.
57
+ #
58
+ # I inspected the MRI source code and didn't find
59
+ # anything that would explain this behavior. This makes
60
+ # me think that it's a glibc bug, but that's very
61
+ # unlikely.
62
+ #
63
+ # The rb_fwrite() implementation takes an entirely
64
+ # different code path if I set 'sync' to true: it will
65
+ # skip fwrite() and use write() instead. So here we set
66
+ # 'sync' to true in the hope that this will work around
67
+ # the problem.
68
+ socket.sync = true
69
+
70
+ # There's no need to set the encoding for Ruby 1.9 because
71
+ # abstract_request_handler.rb is tagged with 'encoding: binary'.
72
+
73
+ @socket = socket
74
+
75
+ return self
76
+ end
77
+
78
+ # Don't allow disabling of sync.
79
+ def sync=(value)
80
+ end
81
+
82
+ # Socket is sync'ed so flushing shouldn't do anything.
83
+ def flush
84
+ end
85
+
86
+ # Already set to binary mode.
87
+ def binmode
88
+ end
89
+
90
+ # This makes select() work.
91
+ def to_io
92
+ @socket
93
+ end
94
+
95
+ def simulate_eof!
96
+ @simulate_eof = true
97
+ end
98
+
99
+ def stop_simulating_eof!
100
+ @simulate_eof = false
101
+ end
102
+
103
+ def fileno
104
+ @socket.fileno
105
+ end
106
+
107
+ def addr
108
+ @socket.addr
109
+ rescue => e
110
+ raise annotate(e)
111
+ end
112
+
113
+ def write(string)
114
+ @socket.write(string)
115
+ rescue => e
116
+ raise annotate(e)
117
+ end
118
+
119
+ def write_nonblock(string)
120
+ @socket.write_nonblock(string)
121
+ rescue => e
122
+ raise annotate(e)
123
+ end
124
+
125
+ def writev(components)
126
+ @socket.writev(components)
127
+ rescue => e
128
+ raise annotate(e)
129
+ end if IO.method_defined?(:writev)
130
+
131
+ def writev2(components, components2)
132
+ @socket.writev2(components, components2)
133
+ rescue => e
134
+ raise annotate(e)
135
+ end if IO.method_defined?(:writev2)
136
+
137
+ def writev3(components, components2, components3)
138
+ @socket.writev3(components, components2, components3)
139
+ rescue => e
140
+ raise annotate(e)
141
+ end if IO.method_defined?(:writev3)
142
+
143
+ def send(*args)
144
+ @socket.send(*args)
145
+ rescue => e
146
+ raise annotate(e)
147
+ end
148
+
149
+ def sendmsg(*args)
150
+ @socket.sendmsg(*args)
151
+ rescue => e
152
+ raise annotate(e)
153
+ end
154
+
155
+ def sendmsg_nonblock(*args)
156
+ @socket.sendmsg_nonblock(*args)
157
+ rescue => e
158
+ raise annotate(e)
159
+ end
160
+
161
+ def puts(*args)
162
+ @socket.puts(*args)
163
+ rescue => e
164
+ raise annotate(e)
165
+ end
166
+
167
+ def gets
168
+ return nil if @simulate_eof
169
+ @socket.gets
170
+ rescue => e
171
+ raise annotate(e)
172
+ end
173
+
174
+ def read(*args)
175
+ if @simulate_eof
176
+ length, buffer = args
177
+ if buffer
178
+ buffer.replace(binary_string(""))
179
+ else
180
+ buffer = binary_string("")
181
+ end
182
+ if length
183
+ return nil
184
+ else
185
+ return buffer
186
+ end
187
+ end
188
+ @socket.read(*args)
189
+ rescue => e
190
+ raise annotate(e)
191
+ end
192
+
193
+ def read_nonblock(*args)
194
+ raise EOFError, "end of file reached" if @simulate_eof
195
+ @socket.read_nonblock(*args)
196
+ rescue => e
197
+ raise annotate(e)
198
+ end
199
+
200
+ def readpartial(*args)
201
+ raise EOFError, "end of file reached" if @simulate_eof
202
+ @socket.readpartial(*args)
203
+ rescue => e
204
+ raise annotate(e)
205
+ end
206
+
207
+ def readline
208
+ raise EOFError, "end of file reached" if @simulate_eof
209
+ @socket.readline
210
+ rescue => e
211
+ raise annotate(e)
212
+ end
213
+
214
+ def recv(*args)
215
+ raise EOFError, "end of file reached" if @simulate_eof
216
+ @socket.recv(*args)
217
+ rescue => e
218
+ raise annotate(e)
219
+ end
220
+
221
+ def recvfrom(*args)
222
+ raise EOFError, "end of file reached" if @simulate_eof
223
+ @socket.recvfrom(*args)
224
+ rescue => e
225
+ raise annotate(e)
226
+ end
227
+
228
+ def recvfrom_nonblock(*args)
229
+ raise EOFError, "end of file reached" if @simulate_eof
230
+ @socket.recvfrom_nonblock(*args)
231
+ rescue => e
232
+ raise annotate(e)
233
+ end
234
+
235
+ def each(&block)
236
+ return if @simulate_eof
237
+ @socket.each(&block)
238
+ rescue => e
239
+ raise annotate(e)
240
+ end
241
+
242
+ def eof?
243
+ return true if @simulate_eof
244
+ @socket.eof?
245
+ rescue => e
246
+ raise annotate(e)
247
+ end
248
+
249
+ def closed?
250
+ @socket.closed?
251
+ rescue => e
252
+ raise annotate(e)
253
+ end
254
+
255
+ def close
256
+ @socket.close
257
+ rescue => e
258
+ raise annotate(e)
259
+ end
260
+
261
+ def close_read
262
+ @socket.close_read
263
+ rescue => e
264
+ raise annotate(e)
265
+ end
266
+
267
+ def close_write
268
+ @socket.close_write
269
+ rescue => e
270
+ raise annotate(e)
271
+ end
272
+
273
+ def source_of_exception?(exception)
274
+ return exception.instance_variable_get(:"@from_unseekable_socket") == @socket.object_id
275
+ end
276
+
277
+ private
278
+ def annotate(exception)
279
+ exception.instance_variable_set(:"@from_unseekable_socket", @socket.object_id)
280
+ return exception
281
+ end
282
+
283
+ def raise_error_because_activity_disallowed!
284
+ raise IOError, "It is not possible to read or write from the client socket because the current."
285
+ end
286
+
287
+ if ''.respond_to?(:force_encoding)
288
+ def binary_string(str)
289
+ return ''.force_encoding('binary')
290
+ end
291
+ else
292
+ def binary_string(str)
293
+ return ''
294
+ end
295
+ end
296
+ end
297
+
298
+ end # module Utils
299
299
  end # module PhusionPassenger