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
@@ -417,10 +417,13 @@ passenger_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
417
417
  {
418
418
  passenger_loc_conf_t *prev = parent;
419
419
  passenger_loc_conf_t *conf = child;
420
+ ngx_http_core_loc_conf_t *clcf;
420
421
 
421
422
  size_t size;
422
423
  ngx_hash_init_t hash;
423
424
 
425
+ clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
426
+
424
427
  #include "MergeLocationConfig.c"
425
428
  if (prev->options_cache.data == NULL) {
426
429
  if (cache_loc_conf_options(cf, prev) != NGX_OK) {
@@ -742,6 +745,10 @@ passenger_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
742
745
  conf->upstream_config.upstream = prev->upstream_config.upstream;
743
746
  }
744
747
 
748
+ if (conf->enabled) {
749
+ clcf->handler = passenger_content_handler;
750
+ }
751
+
745
752
  conf->headers_hash_bucket_size = ngx_align(conf->headers_hash_bucket_size,
746
753
  ngx_cacheline_size);
747
754
  hash.max_size = conf->headers_hash_max_size;
@@ -400,7 +400,7 @@ prepare_request_buffer_construction(ngx_http_request_t *r, passenger_context_t *
400
400
 
401
401
  state->app_type.data = (u_char *) pp_get_app_type_name(context->app_type);
402
402
  /* Include null terminator */
403
- state->app_type.len = strlen((const char *) state->app_type.data) + 1;
403
+ state->app_type.len = strlen((const char *) state->app_type.data);
404
404
 
405
405
  /*
406
406
  * Nginx unescapes URI's before passing them to Phusion Passenger,
@@ -676,6 +676,14 @@ construct_request_buffer(ngx_http_request_t *r, passenger_loc_conf_t *slcf,
676
676
  PUSH_STATIC_STR("\r\n");
677
677
  }
678
678
 
679
+ PUSH_STATIC_STR("!~PASSENGER_APP_TYPE: ");
680
+ if (b != NULL) {
681
+ b->last = ngx_copy(b->last, state->app_type.data,
682
+ state->app_type.len);
683
+ }
684
+ total_size += state->app_type.len;
685
+ PUSH_STATIC_STR("\r\n");
686
+
679
687
  if (slcf->union_station_filters != NGX_CONF_UNSET_PTR
680
688
  && slcf->union_station_filters->nelts > 0)
681
689
  {
@@ -27,48 +27,52 @@
27
27
  # file locations.
28
28
 
29
29
  class Addr2line
30
- attr_reader :stdin, :stdout, :pid
30
+ attr_reader :stdin, :stdout, :pid
31
31
 
32
- def initialize(filename)
33
- a, b = IO.pipe
34
- c, d = IO.pipe
35
- @pid = fork do
36
- STDIN.reopen(a)
37
- b.close
38
- STDOUT.reopen(d)
39
- c.close
40
- exec("addr2line", "-Cfie", filename)
41
- end
42
- a.close
43
- d.close
44
- @stdin = b
45
- @stdout = c
46
- @stdin.sync = @stdout.sync = true
47
- end
32
+ def initialize(filename)
33
+ a, b = IO.pipe
34
+ c, d = IO.pipe
35
+ @pid = fork do
36
+ STDIN.reopen(a)
37
+ b.close
38
+ STDOUT.reopen(d)
39
+ c.close
40
+ exec("addr2line", "-Cfie", filename)
41
+ end
42
+ a.close
43
+ d.close
44
+ @stdin = b
45
+ @stdout = c
46
+ @stdin.sync = @stdout.sync = true
47
+ end
48
48
 
49
- def query(address)
50
- @stdin.write("#{address}\n")
51
- function = @stdout.readline
52
- source = @stdout.readline
53
- function.strip!
54
- source.strip!
55
- return [function, source]
56
- end
49
+ def query(address)
50
+ @stdin.write("#{address}\n")
51
+ function = @stdout.readline
52
+ source = @stdout.readline
53
+ function.strip!
54
+ source.strip!
55
+ return [function, source]
56
+ end
57
57
 
58
- def close
59
- @stdin.close
60
- @stdout.close
61
- Process.kill('KILL', @pid)
62
- Process.waitpid(@pid) rescue nil
63
- end
58
+ def close
59
+ @stdin.close
60
+ @stdout.close
61
+ Process.kill('KILL', @pid)
62
+ Process.waitpid(@pid) rescue nil
63
+ end
64
64
  end
65
65
 
66
66
  def passthrough(input, output)
67
- while !input.eof?
68
- data = input.readline
69
- output.write(data)
70
- output.flush
71
- end
67
+ while !input.eof?
68
+ data = input.readline
69
+ output.write(data)
70
+ output.flush
71
+ end
72
+ end
73
+
74
+ def debug(message)
75
+ #puts message
72
76
  end
73
77
 
74
78
  input = STDIN
@@ -77,63 +81,78 @@ output.sync = true
77
81
  output.puts "Using backtrace sanitizer."
78
82
  argv0, pid_or_filename = ARGV
79
83
  if pid_or_filename =~ /\A\d+\Z/
80
- begin
81
- exe_filename = File.expand_path(File.readlink("/proc/#{pid_or_filename}/exe"))
82
- rescue Errno::ENOENT, Errno::EACCES => e
83
- warn "*** backtrace-sanitizer warning: #{e} -> passthrough input"
84
- passthrough(input, output)
85
- exit
86
- end
84
+ begin
85
+ exe_filename = File.expand_path(File.readlink("/proc/#{pid_or_filename}/exe"))
86
+ rescue Errno::ENOENT, Errno::EACCES => e
87
+ warn "*** backtrace-sanitizer warning: #{e} -> passthrough input"
88
+ passthrough(input, output)
89
+ exit
90
+ end
87
91
  else
88
- exe_filename = File.expand_path(pid_or_filename)
92
+ exe_filename = File.expand_path(pid_or_filename)
89
93
  end
90
94
  exe_basename = File.basename(exe_filename)
91
95
  addr2lines = {}
92
96
 
93
97
  begin
94
- while !input.eof?
95
- line = input.readline.strip
96
- # Example lines:
97
- # ./test() [0x400b64]
98
- # /lib/libc.so.6(__libc_start_main+0xfd) [0x7fcc0ad00c8d]
99
- if line =~ /(.*)\[(.*?)\]$/
100
- # Split line into:
101
- # subject: /lib/libc.so.6(__libc_start_main+0xfd)
102
- # address: 0x7fcc0ad00c8d
103
- subject = $1
104
- address = $2
105
- subject.strip!
106
- subject =~ /(.*?)(\((.*?)\))?$/
107
- # Split subject into:
108
- # file: /lib/libc.so.6
109
- # context: __libc_start_main+0xfd
110
- file = $1
111
- context = $3
112
- file.strip!
113
- context = nil if context && context.empty?
98
+ while !input.eof?
99
+ line = input.readline.strip
100
+ debug " ---> Parse #{line.inspect}"
101
+
102
+ # Example lines:
103
+ # ./test() [0x400b64]
104
+ # /lib/libc.so.6(__libc_start_main+0xfd) [0x7fcc0ad00c8d]
105
+ # PassengerAgent server[0x4d2697]
106
+ if line =~ /(.*)\[(.*?)\]$/
107
+ # Split line into:
108
+ # subject: /lib/libc.so.6(__libc_start_main+0xfd)
109
+ # address: 0x7fcc0ad00c8d
110
+ subject = $1
111
+ address = $2
112
+ subject.strip!
113
+
114
+ if subject =~ /(.*?)(\((.*?)\))?$/
115
+ # Split subject into:
116
+ # file: /lib/libc.so.6
117
+ # context: __libc_start_main+0xfd
118
+ file = $1
119
+ context = $3
120
+ file.strip!
121
+ context = nil if context && context.empty?
122
+ else
123
+ file = subject
124
+ context = nil
125
+ end
126
+
127
+ debug " file = #{file.inspect}"
128
+ debug " context = #{context.inspect}"
129
+ debug " address = #{address.inspect}"
114
130
 
115
- if file =~ /\A\// && File.exist?(file)
116
- filename = file
117
- elsif file == argv0 || file == exe_filename || file == exe_basename
118
- filename = exe_filename
119
- else
120
- filename = nil
121
- end
122
- if filename.nil?
123
- output.puts line
124
- else
125
- addr2line = (addr2lines[filename] ||= Addr2line.new(filename))
126
- function, source = addr2line.query(address)
127
- new_context = "#{function} at #{source}"
128
- new_context << "; #{context}" if context
129
- output.puts "#{file}(#{new_context}) [#{address}]"
130
- end
131
- else
132
- output.puts line
133
- end
134
- end
131
+ if file =~ /\A\// && File.exist?(file)
132
+ filename = file
133
+ elsif file == argv0 ||
134
+ file == exe_filename ||
135
+ file == exe_basename ||
136
+ file.sub(/ .*/, '') == exe_basename
137
+ filename = exe_filename
138
+ else
139
+ filename = nil
140
+ end
141
+ if filename.nil?
142
+ output.puts line
143
+ else
144
+ addr2line = (addr2lines[filename] ||= Addr2line.new(filename))
145
+ function, source = addr2line.query(address)
146
+ new_context = "#{function} at #{source}"
147
+ new_context << "; #{context}" if context
148
+ output.puts "#{file}(#{new_context}) [#{address}]"
149
+ end
150
+ else
151
+ output.puts line
152
+ end
153
+ end
135
154
  ensure
136
- addr2lines.each_value do |addr2line|
137
- addr2line.close
138
- end
155
+ addr2lines.each_value do |addr2line|
156
+ addr2line.close
157
+ end
139
158
  end
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright (c) 2015 Phusion
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ # This script uses GDB to attach to a process in order to dump the
24
+ # backtraces of all its threads.
25
+
26
+ ruby_libdir = ARGV.shift
27
+ passenger_root = ARGV.shift
28
+ require "#{ruby_libdir}/phusion_passenger"
29
+ PhusionPassenger.locate_directories(passenger_root)
30
+
31
+ PhusionPassenger.require_passenger_lib 'vendor/crash_watch/app'
32
+ CrashWatch::App.new.run(ARGV)
@@ -27,10 +27,10 @@
27
27
 
28
28
  # Create a dummy Makefile to prevent 'gem install' from borking out.
29
29
  File.open("Makefile", "w") do |f|
30
- f.puts "all:"
31
- f.puts " true"
32
- f.puts "install:"
33
- f.puts " true"
30
+ f.puts "all:"
31
+ f.puts " true"
32
+ f.puts "install:"
33
+ f.puts " true"
34
34
  end
35
35
 
36
36
  # Don't do anything on Windows. We don't support Windows but exiting now
@@ -44,12 +44,12 @@ PhusionPassenger.locate_directories
44
44
  require 'fileutils'
45
45
 
46
46
  if PhusionPassenger.custom_packaged?
47
- puts "Binary downloading is only available when originally packaged. Stopping."
48
- exit 0
47
+ puts "Binary downloading is only available when originally packaged. Stopping."
48
+ exit 0
49
49
  end
50
50
  if !PhusionPassenger.installed_from_release_package?
51
- puts "This Phusion Passenger is not installed from an official release package. Stopping."
52
- exit 0
51
+ puts "This Phusion Passenger is not installed from an official release package. Stopping."
52
+ exit 0
53
53
  end
54
54
 
55
55
  # Create download directory and do some preparation
@@ -60,9 +60,9 @@ ruby_compat_id = PhusionPassenger::PlatformInfo.ruby_extension_binary_compatibil
60
60
 
61
61
  ABORT_ON_ERROR = ARGV[0] == "--abort-on-error"
62
62
  if url_root = ENV['BINARIES_URL_ROOT']
63
- SITES = [{ :url => url_root }]
63
+ SITES = [{ :url => url_root }]
64
64
  else
65
- SITES = PhusionPassenger.binaries_sites
65
+ SITES = PhusionPassenger.binaries_sites
66
66
  end
67
67
 
68
68
  FileUtils.mkdir_p(PhusionPassenger.download_cache_dir)
@@ -73,40 +73,40 @@ require 'phusion_passenger/utils/download'
73
73
  require 'logger'
74
74
 
75
75
  def download(name, options = {})
76
- if File.exist?(name)
77
- puts "#{Dir.pwd}/#{name} already exists"
78
- return true
79
- end
76
+ if File.exist?(name)
77
+ puts "#{Dir.pwd}/#{name} already exists"
78
+ return true
79
+ end
80
80
 
81
- logger = Logger.new(STDOUT)
82
- logger.level = Logger::WARN
83
- logger.formatter = proc { |severity, datetime, progname, msg| "*** #{msg}\n" }
81
+ logger = Logger.new(STDOUT)
82
+ logger.level = Logger::WARN
83
+ logger.formatter = proc { |severity, datetime, progname, msg| "*** #{msg}\n" }
84
84
 
85
- SITES.each do |site|
86
- if really_download(site, name, logger, options)
87
- return true
88
- end
89
- end
90
- abort "Cannot download #{name}, aborting" if ABORT_ON_ERROR
91
- return false
85
+ SITES.each do |site|
86
+ if really_download(site, name, logger, options)
87
+ return true
88
+ end
89
+ end
90
+ abort "Cannot download #{name}, aborting" if ABORT_ON_ERROR
91
+ return false
92
92
  end
93
93
 
94
94
  def really_download(site, name, logger, options)
95
- url = "#{site[:url]}/#{PhusionPassenger::VERSION_STRING}/#{name}"
96
- puts "Attempting to download #{url} into #{Dir.pwd}"
97
- File.unlink("#{name}.tmp") rescue nil
95
+ url = "#{site[:url]}/#{PhusionPassenger::VERSION_STRING}/#{name}"
96
+ puts "Attempting to download #{url} into #{Dir.pwd}"
97
+ File.unlink("#{name}.tmp") rescue nil
98
98
 
99
- options = {
100
- :cacert => site[:cert],
101
- :logger => logger
102
- }.merge(options)
103
- result = PhusionPassenger::Utils::Download.download(url, "#{name}.tmp", options)
104
- if result
105
- File.rename("#{name}.tmp", name)
106
- else
107
- File.unlink("#{name}.tmp") rescue nil
108
- end
109
- return result
99
+ options = {
100
+ :cacert => site[:cert],
101
+ :logger => logger
102
+ }.merge(options)
103
+ result = PhusionPassenger::Utils::Download.download(url, "#{name}.tmp", options)
104
+ if result
105
+ File.rename("#{name}.tmp", name)
106
+ else
107
+ File.unlink("#{name}.tmp") rescue nil
108
+ end
109
+ return result
110
110
  end
111
111
 
112
112
  download "rubyext-#{ruby_compat_id}.tar.gz", :total_timeout => 10
@@ -28,124 +28,124 @@ require 'thread'
28
28
  require 'logger'
29
29
 
30
30
  module PhusionPassenger
31
- module App
32
- def self.options
33
- return @@options
34
- end
31
+ module App
32
+ def self.options
33
+ return @@options
34
+ end
35
35
 
36
- def self.exit_code_for_exception(e)
37
- if e.is_a?(SystemExit)
38
- return e.status
39
- else
40
- return 1
41
- end
42
- end
36
+ def self.exit_code_for_exception(e)
37
+ if e.is_a?(SystemExit)
38
+ return e.status
39
+ else
40
+ return 1
41
+ end
42
+ end
43
43
 
44
- def self.handshake_and_read_startup_request
45
- STDOUT.sync = true
46
- STDERR.sync = true
47
- puts "!> I have control 1.0"
48
- abort "Invalid initialization header" if STDIN.readline != "You have control 1.0\n"
44
+ def self.handshake_and_read_startup_request
45
+ STDOUT.sync = true
46
+ STDERR.sync = true
47
+ puts "!> I have control 1.0"
48
+ abort "Invalid initialization header" if STDIN.readline != "You have control 1.0\n"
49
49
 
50
- @@options = {}
51
- while (line = STDIN.readline) != "\n"
52
- name, value = line.strip.split(/: */, 2)
53
- @@options[name] = value
54
- end
55
- end
50
+ @@options = {}
51
+ while (line = STDIN.readline) != "\n"
52
+ name, value = line.strip.split(/: */, 2)
53
+ @@options[name] = value
54
+ end
55
+ end
56
56
 
57
- def self.init_passenger
58
- require "#{options["ruby_libdir"]}/phusion_passenger"
59
- PhusionPassenger.locate_directories(options["passenger_root"])
60
- PhusionPassenger.require_passenger_lib 'message_channel'
61
- PhusionPassenger.require_passenger_lib 'utils/tmpio'
62
- end
57
+ def self.init_passenger
58
+ require "#{options["ruby_libdir"]}/phusion_passenger"
59
+ PhusionPassenger.locate_directories(options["passenger_root"])
60
+ PhusionPassenger.require_passenger_lib 'message_channel'
61
+ PhusionPassenger.require_passenger_lib 'utils/tmpio'
62
+ end
63
63
 
64
- def self.ping_port(port)
65
- socket_domain = Socket::Constants::AF_INET
66
- sockaddr = Socket.pack_sockaddr_in(port, '127.0.0.1')
67
- begin
68
- socket = Socket.new(socket_domain, Socket::Constants::SOCK_STREAM, 0)
69
- begin
70
- socket.connect_nonblock(sockaddr)
71
- rescue Errno::ENOENT, Errno::EINPROGRESS, Errno::EAGAIN, Errno::EWOULDBLOCK
72
- if select(nil, [socket], nil, 0.1)
73
- begin
74
- socket.connect_nonblock(sockaddr)
75
- rescue Errno::EISCONN
76
- end
77
- else
78
- raise Errno::ECONNREFUSED
79
- end
80
- end
81
- return true
82
- rescue Errno::ECONNREFUSED, Errno::ENOENT
83
- return false
84
- ensure
85
- socket.close if socket
86
- end
87
- end
64
+ def self.ping_port(port)
65
+ socket_domain = Socket::Constants::AF_INET
66
+ sockaddr = Socket.pack_sockaddr_in(port, '127.0.0.1')
67
+ begin
68
+ socket = Socket.new(socket_domain, Socket::Constants::SOCK_STREAM, 0)
69
+ begin
70
+ socket.connect_nonblock(sockaddr)
71
+ rescue Errno::ENOENT, Errno::EINPROGRESS, Errno::EAGAIN, Errno::EWOULDBLOCK
72
+ if select(nil, [socket], nil, 0.1)
73
+ begin
74
+ socket.connect_nonblock(sockaddr)
75
+ rescue Errno::EISCONN
76
+ end
77
+ else
78
+ raise Errno::ECONNREFUSED
79
+ end
80
+ end
81
+ return true
82
+ rescue Errno::ECONNREFUSED, Errno::ENOENT
83
+ return false
84
+ ensure
85
+ socket.close if socket
86
+ end
87
+ end
88
88
 
89
- def self.load_app
90
- port = nil
91
- tries = 0
92
- while port.nil? && tries < 200
93
- port = 1024 + rand(9999)
94
- if ping_port(port) || ping_port(port + 1) || ping_port(port + 2)
95
- port = nil
96
- tries += 1
97
- end
98
- end
99
- if port.nil?
100
- abort "Cannot find a suitable port to start Meteor on"
101
- end
89
+ def self.load_app
90
+ port = nil
91
+ tries = 0
92
+ while port.nil? && tries < 200
93
+ port = 1024 + rand(9999)
94
+ if ping_port(port) || ping_port(port + 1) || ping_port(port + 2)
95
+ port = nil
96
+ tries += 1
97
+ end
98
+ end
99
+ if port.nil?
100
+ abort "Cannot find a suitable port to start Meteor on"
101
+ end
102
102
 
103
- production = options["environment"] == "production" ? "--production" : ""
104
- pid = fork do
105
- # Meteor is quite !@#$% here: if we kill its start script
106
- # with *any* signal, it'll leave a ton of garbage processes
107
- # around. Apparently it expects the user to press Ctrl-C in a
108
- # terminal which happens to send a signal to all processes
109
- # in the session. We emulate that behavior here by giving
110
- # Meteor its own process group, and sending signals to the
111
- # entire process group.
112
- Process.setpgrp
113
- exec("meteor run -p #{port} #{production}")
114
- end
115
- $0 = options["process_title"] if options["process_title"]
116
- $0 = "#{$0} (#{pid})"
117
- return [pid, port]
118
- end
103
+ production = options["environment"] == "production" ? "--production" : ""
104
+ pid = fork do
105
+ # Meteor is quite !@#$% here: if we kill its start script
106
+ # with *any* signal, it'll leave a ton of garbage processes
107
+ # around. Apparently it expects the user to press Ctrl-C in a
108
+ # terminal which happens to send a signal to all processes
109
+ # in the session. We emulate that behavior here by giving
110
+ # Meteor its own process group, and sending signals to the
111
+ # entire process group.
112
+ Process.setpgrp
113
+ exec("meteor run -p #{port} #{production}")
114
+ end
115
+ $0 = options["process_title"] if options["process_title"]
116
+ $0 = "#{$0} (#{pid})"
117
+ return [pid, port]
118
+ end
119
119
 
120
- def self.wait_for_exit_message
121
- begin
122
- STDIN.readline
123
- rescue EOFError
124
- end
125
- end
120
+ def self.wait_for_exit_message
121
+ begin
122
+ STDIN.readline
123
+ rescue EOFError
124
+ end
125
+ end
126
126
 
127
127
 
128
- ################## Main code ##################
128
+ ################## Main code ##################
129
129
 
130
130
 
131
- handshake_and_read_startup_request
132
- init_passenger
133
- begin
134
- pid, port = load_app
135
- while !ping_port(port)
136
- sleep 0.01
137
- end
138
- puts "!> Ready"
139
- puts "!> socket: main;tcp://127.0.0.1:#{port};http_session;0"
140
- puts "!> "
141
- wait_for_exit_message
142
- ensure
143
- if pid
144
- Process.kill('INT', -pid) rescue nil
145
- Process.waitpid(pid) rescue nil
146
- Process.kill('INT', -pid) rescue nil
147
- end
148
- end
131
+ handshake_and_read_startup_request
132
+ init_passenger
133
+ begin
134
+ pid, port = load_app
135
+ while !ping_port(port)
136
+ sleep 0.01
137
+ end
138
+ puts "!> Ready"
139
+ puts "!> socket: main;tcp://127.0.0.1:#{port};http_session;0"
140
+ puts "!> "
141
+ wait_for_exit_message
142
+ ensure
143
+ if pid
144
+ Process.kill('INT', -pid) rescue nil
145
+ Process.waitpid(pid) rescue nil
146
+ Process.kill('INT', -pid) rescue nil
147
+ end
148
+ end
149
149
 
150
- end # module App
150
+ end # module App
151
151
  end # module PhusionPassenger