passenger 5.0.28 → 5.0.29

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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +5 -0
  3. data/CHANGELOG +13 -0
  4. data/build/apache2.rb +3 -3
  5. data/build/common_library.rb +3 -3
  6. data/build/nginx.rb +4 -4
  7. data/build/packaging.rb +9 -8
  8. data/build/support/cxx_dependency_map.rb +9 -7
  9. data/build/support/general.rb +39 -0
  10. data/build/support/vendor/cxxcodebuilder/CxxCodeBuilder.sublime-project +8 -0
  11. data/build/support/vendor/cxxcodebuilder/Gemfile +4 -0
  12. data/build/support/vendor/cxxcodebuilder/Gemfile.lock +28 -0
  13. data/build/support/vendor/cxxcodebuilder/LICENSE.md +19 -0
  14. data/build/support/vendor/cxxcodebuilder/README.md +98 -0
  15. data/build/support/vendor/cxxcodebuilder/Rakefile +4 -0
  16. data/build/support/vendor/cxxcodebuilder/lib/cxxcodebuilder.rb +23 -0
  17. data/build/support/vendor/cxxcodebuilder/lib/cxxcodebuilder/builder.rb +574 -0
  18. data/build/support/vendor/cxxcodebuilder/lib/cxxcodebuilder/initializer_builder.rb +166 -0
  19. data/build/test_basics.rb +2 -1
  20. data/resources/templates/standalone/server.erb +6 -4
  21. data/src/agent/Core/Controller/ForwardResponse.cpp +5 -5
  22. data/src/agent/Watchdog/WatchdogMain.cpp +0 -10
  23. data/src/apache2_module/ConfigurationCommands.cpp +181 -248
  24. data/src/apache2_module/ConfigurationCommands.cpp.cxxcodebuilder +127 -0
  25. data/src/apache2_module/ConfigurationFields.hpp +135 -51
  26. data/src/apache2_module/ConfigurationFields.hpp.cxxcodebuilder +113 -0
  27. data/src/apache2_module/ConfigurationSetters.cpp +414 -459
  28. data/src/apache2_module/ConfigurationSetters.cpp.cxxcodebuilder +144 -0
  29. data/src/apache2_module/CreateDirConfig.cpp +49 -52
  30. data/src/apache2_module/CreateDirConfig.cpp.cxxcodebuilder +81 -0
  31. data/src/apache2_module/Hooks.cpp +0 -14
  32. data/src/apache2_module/MergeDirConfig.cpp +136 -226
  33. data/src/apache2_module/MergeDirConfig.cpp.cxxcodebuilder +97 -0
  34. data/src/apache2_module/SetHeaders.cpp +92 -143
  35. data/src/apache2_module/SetHeaders.cpp.cxxcodebuilder +106 -0
  36. data/src/cxx_supportlib/Constants.h +86 -146
  37. data/src/cxx_supportlib/Constants.h.cxxcodebuilder +43 -0
  38. data/src/cxx_supportlib/DataStructures/LString.h +40 -23
  39. data/src/cxx_supportlib/MemoryKit/mbuf.cpp +60 -25
  40. data/src/cxx_supportlib/MemoryKit/mbuf.h +50 -25
  41. data/src/cxx_supportlib/ServerKit/CookieUtils.h +36 -3
  42. data/src/cxx_supportlib/ServerKit/HeaderTable.h +2 -8
  43. data/src/cxx_supportlib/ServerKit/HttpServer.h +6 -15
  44. data/src/cxx_supportlib/WatchdogLauncher.cpp +4 -4
  45. data/src/cxx_supportlib/WatchdogLauncher.h +2 -3
  46. data/src/nginx_module/CacheLocationConfig.c +623 -780
  47. data/src/nginx_module/CacheLocationConfig.c.cxxcodebuilder +214 -0
  48. data/src/nginx_module/Configuration.h +1 -1
  49. data/src/nginx_module/ConfigurationCommands.c +404 -535
  50. data/src/nginx_module/ConfigurationCommands.c.cxxcodebuilder +157 -0
  51. data/src/nginx_module/CreateLocationConfig.c +82 -206
  52. data/src/nginx_module/CreateLocationConfig.c.cxxcodebuilder +98 -0
  53. data/src/nginx_module/LocationConfig.h +97 -0
  54. data/src/nginx_module/LocationConfig.h.cxxcodebuilder +131 -0
  55. data/src/nginx_module/MergeLocationConfig.c +157 -278
  56. data/src/nginx_module/MergeLocationConfig.c.cxxcodebuilder +144 -0
  57. data/src/nginx_module/ngx_http_passenger_module.c +4 -10
  58. data/src/ruby_supportlib/phusion_passenger.rb +4 -4
  59. data/src/ruby_supportlib/phusion_passenger/config/validate_install_command.rb +2 -2
  60. data/src/ruby_supportlib/phusion_passenger/packaging.rb +2 -0
  61. data/src/ruby_supportlib/phusion_passenger/platform_info/compiler.rb +6 -0
  62. data/src/ruby_supportlib/phusion_passenger/platform_info/cxx_portability.rb +1 -1
  63. data/src/ruby_supportlib/phusion_passenger/standalone/start_command.rb +27 -8
  64. data/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller.rb +120 -2
  65. data/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller/lock_file.rb +1 -1
  66. data/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller/spawn.rb +4 -4
  67. data/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller/version.rb +1 -1
  68. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/api.rb +5 -5
  69. metadata +24 -15
  70. data/src/apache2_module/ConfigurationCommands.cpp.erb +0 -109
  71. data/src/apache2_module/ConfigurationFields.hpp.erb +0 -98
  72. data/src/apache2_module/ConfigurationSetters.cpp.erb +0 -128
  73. data/src/apache2_module/CreateDirConfig.cpp.erb +0 -72
  74. data/src/apache2_module/MergeDirConfig.cpp.erb +0 -82
  75. data/src/apache2_module/SetHeaders.cpp.erb +0 -91
  76. data/src/cxx_supportlib/Constants.h.erb +0 -41
  77. data/src/nginx_module/CacheLocationConfig.c.erb +0 -171
  78. data/src/nginx_module/ConfigurationCommands.c.erb +0 -144
  79. data/src/nginx_module/ConfigurationFields.h +0 -145
  80. data/src/nginx_module/ConfigurationFields.h.erb +0 -112
  81. data/src/nginx_module/CreateLocationConfig.c.erb +0 -78
  82. data/src/nginx_module/MergeLocationConfig.c.erb +0 -118
@@ -0,0 +1,144 @@
1
+ # Phusion Passenger - https://www.phusionpassenger.com/
2
+ # Copyright (c) 2010-2016 Phusion Holding B.V.
3
+ #
4
+ # "Passenger", "Phusion Passenger" and "Union Station" are registered
5
+ # trademarks of Phusion Holding B.V.
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in
15
+ # all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ # THE SOFTWARE.
24
+
25
+ # This file uses the cxxcodebuilder API. Learn more at:
26
+ # https://github.com/phusion/passenger/cxxcodebuilder
27
+
28
+ require 'phusion_passenger/nginx/config_options'
29
+
30
+ def main
31
+ set_indent_string ' '
32
+ comment copyright_header_for(__FILE__)
33
+
34
+ separator
35
+
36
+ comment %q{
37
+ MergeLocationConfig.c is automatically generated from MergeLocationConfig.c.cxxcodebuilder,
38
+ using definitions from src/ruby_supportlib/phusion_passenger/nginx/config_options.rb.
39
+ Edits to MergeLocationConfig.c will be lost.
40
+
41
+ To update MergeLocationConfig.c:
42
+ rake nginx
43
+
44
+ To force regeneration of MergeLocationConfig.c:
45
+ rm -f src/nginx_module/MergeLocationConfig.c
46
+ rake src/nginx_module/MergeLocationConfig.c
47
+ }
48
+
49
+ separator
50
+
51
+ comment %q{
52
+ 0: NGX_CONF_ERROR, 1: OK
53
+ }
54
+ function('int generated_merge_part(passenger_loc_conf_t *conf, passenger_loc_conf_t *prev, ngx_conf_t *cf)') do
55
+ filter_eligible_options(LOCATION_CONFIGURATION_OPTIONS).each do |option|
56
+ if option[:type] == :string
57
+ add_code %Q{
58
+ ngx_conf_merge_str_value(conf->#{struct_field_for(option)},
59
+ prev->#{struct_field_for(option)},
60
+ NULL);
61
+ }
62
+ elsif option[:type] == :integer || option[:type] == :flag
63
+ add_code %Q{
64
+ ngx_conf_merge_value(conf->#{struct_field_for(option)},
65
+ prev->#{struct_field_for(option)},
66
+ NGX_CONF_UNSET);
67
+ }
68
+ elsif option[:type] == :uinteger
69
+ add_code %Q{
70
+ ngx_conf_merge_uint_value(conf->#{struct_field_for(option)},
71
+ prev->#{struct_field_for(option)},
72
+ #{default_value_for(option) || "NGX_CONF_UNSET_UINT"});
73
+ }
74
+ elsif option[:type] == :string_array
75
+ add_code %Q{
76
+ if (merge_string_array(cf, &prev->#{struct_field_for(option)}, &conf->#{struct_field_for(option)}) != NGX_OK) {
77
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
78
+ "cannot merge \\"#{option[:name]}\\" configurations");
79
+ return 0;
80
+ }
81
+ }
82
+ elsif option[:type] == :string_keyval
83
+ add_code %Q{
84
+ if (merge_string_keyval_table(cf, &prev->#{struct_field_for(option)}, &conf->#{struct_field_for(option)}) != NGX_OK) {
85
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
86
+ "cannot merge \\"#{option[:name]}\\" configurations");
87
+ return 0;
88
+ }
89
+ }
90
+ else
91
+ raise "Unknown option type #{option[:type].inspect} for option #{option[:name]}"
92
+ end
93
+ end
94
+
95
+ separator
96
+ add_code %q{
97
+ return 1;
98
+ }
99
+ end
100
+ end
101
+
102
+ def filter_eligible_options(options)
103
+ options.reject do |option|
104
+ option[:alias_for] ||
105
+ option.fetch(:field, true).nil? ||
106
+ option[:field].to_s =~ /\./ ||
107
+ !option.fetch(:auto_generate_nginx_merge_code, true)
108
+ end
109
+ end
110
+
111
+ def struct_field_for(option)
112
+ if option.has_key?(:field)
113
+ option[:field]
114
+ else
115
+ option[:name].sub(/^passenger_/, '')
116
+ end
117
+ end
118
+
119
+ def default_value_for(option)
120
+ case option[:type]
121
+ when :string
122
+ if option[:default]
123
+ option[:default].inspect
124
+ else
125
+ "NULL"
126
+ end
127
+ when :integer, :flag
128
+ if option[:default]
129
+ option[:default]
130
+ else
131
+ "NGX_CONF_UNSET"
132
+ end
133
+ when :uinteger
134
+ if option[:default]
135
+ option[:default]
136
+ else
137
+ "NGX_CONF_UNSET_UINT"
138
+ end
139
+ else
140
+ raise "Unknown type #{option[:type].inspect} for option #{option[:name]}"
141
+ end
142
+ end
143
+
144
+ main
@@ -131,7 +131,7 @@ starting_watchdog_after_fork(void *paramCycle, void *paramParams) {
131
131
  ngx_cycle_t *cycle = (void *) paramCycle;
132
132
  PsgVariantMap *params = (void *) paramParams;
133
133
 
134
- const char *log_filename;
134
+ char *log_filename;
135
135
  FILE *log_file;
136
136
  ngx_core_conf_t *ccf;
137
137
  ngx_uint_t i;
@@ -142,7 +142,7 @@ starting_watchdog_after_fork(void *paramCycle, void *paramParams) {
142
142
  * Make sure that they're both redirected to the log file.
143
143
  */
144
144
  log_file = NULL;
145
- log_filename = (const char *) psg_variant_map_get_optional(params, "log_file");
145
+ log_filename = psg_variant_map_get_optional(params, "log_file");
146
146
  if (log_filename == NULL) {
147
147
  ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
148
148
  "no passenger log file configured, discarding log output");
@@ -152,6 +152,8 @@ starting_watchdog_after_fork(void *paramCycle, void *paramParams) {
152
152
  ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
153
153
  "could not open the passenger log file for writing during Nginx startup, some log lines might be lost (will retry from Passenger core)");
154
154
  }
155
+ free(log_filename);
156
+ log_filename = NULL;
155
157
  }
156
158
 
157
159
  if (log_file == NULL) {
@@ -223,7 +225,6 @@ start_watchdog(ngx_cycle_t *cycle) {
223
225
  ngx_core_conf_t *core_conf;
224
226
  ngx_int_t ret, result;
225
227
  ngx_uint_t i;
226
- char *config_file = NULL;
227
228
  ngx_str_t *prestart_uris;
228
229
  char **prestart_uris_ary = NULL;
229
230
  ngx_keyval_t *ctl = NULL;
@@ -243,11 +244,6 @@ start_watchdog(ngx_cycle_t *cycle) {
243
244
  pp_app_type_detector_set_throttle_rate(pp_app_type_detector,
244
245
  passenger_main_conf.stat_throttle_rate);
245
246
 
246
- config_file = ngx_str_null_terminate(&cycle->conf_file);
247
- if (config_file == NULL) {
248
- goto error_enomem;
249
- }
250
-
251
247
  prestart_uris = (ngx_str_t *) passenger_main_conf.prestart_uris->elts;
252
248
  prestart_uris_ary = calloc(sizeof(char *), passenger_main_conf.prestart_uris->nelts);
253
249
  for (i = 0; i < passenger_main_conf.prestart_uris->nelts; i++) {
@@ -258,7 +254,6 @@ start_watchdog(ngx_cycle_t *cycle) {
258
254
  }
259
255
 
260
256
  psg_variant_map_set_int (params, "web_server_control_process_pid", getpid());
261
- psg_variant_map_set_strset (params, "web_server_config_files", (const char **) &config_file, 1);
262
257
  psg_variant_map_set (params, "server_software", NGINX_VER, strlen(NGINX_VER));
263
258
  psg_variant_map_set_bool (params, "multi_app", 1);
264
259
  psg_variant_map_set_bool (params, "load_shell_envvars", 1);
@@ -348,7 +343,6 @@ cleanup:
348
343
  psg_variant_map_free(params);
349
344
  free(passenger_root);
350
345
  free(error_message);
351
- free(config_file);
352
346
  if (prestart_uris_ary != NULL) {
353
347
  for (i = 0; i < passenger_main_conf.prestart_uris->nelts; i++) {
354
348
  free(prestart_uris_ary[i]);
@@ -31,12 +31,12 @@ module PhusionPassenger
31
31
 
32
32
  PACKAGE_NAME = 'passenger'
33
33
  # Run 'rake src/cxx_supportlib/Constants.h' after changing this number.
34
- VERSION_STRING = '5.0.28'
34
+ VERSION_STRING = '5.0.29'
35
35
 
36
- PREFERRED_NGINX_VERSION = '1.10.0'
37
- NGINX_SHA256_CHECKSUM = '8ed647c3dd65bc4ced03b0e0f6bf9e633eff6b01bac772bcf97077d58bc2be4d'
36
+ PREFERRED_NGINX_VERSION = '1.10.1'
37
+ NGINX_SHA256_CHECKSUM = '1fd35846566485e03c0e318989561c135c598323ff349c503a6c14826487a801'
38
38
 
39
- PREFERRED_PCRE_VERSION = '8.34'
39
+ PREFERRED_PCRE_VERSION = '8.39'
40
40
  PCRE_SHA256_CHECKSUM = '1dd78994c81e44ac41cf30b2a21d4b4cc6d76ccde7fc6e77713ed51d7bddca47'
41
41
 
42
42
  STANDALONE_INTERFACE_VERSION = 1
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
  # Phusion Passenger - https://www.phusionpassenger.com/
3
- # Copyright (c) 2014-2015 Phusion Holding B.V.
3
+ # Copyright (c) 2014-2016 Phusion Holding B.V.
4
4
  #
5
5
  # "Passenger", "Phusion Passenger" and "Union Station" are registered
6
6
  # trademarks of Phusion Holding B.V.
@@ -100,7 +100,7 @@ module PhusionPassenger
100
100
  opts.separator " The exit codes are as follows:"
101
101
  opts.separator " 0 - All checks passed. No errors, no warnings."
102
102
  opts.separator " #{FAIL_EXIT_CODE} - Some checks failed with an error."
103
- opts.separator " #{WARN_EXIT_CODE} - No checks failed with an error, but some failed produced warnings."
103
+ opts.separator " #{WARN_EXIT_CODE} - No checks failed with an error, but some produced warnings."
104
104
  opts.separator " #{INTERNAL_ERROR_CODE} - Some internal error occurred."
105
105
  opts.separator ""
106
106
 
@@ -108,6 +108,8 @@ module PhusionPassenger
108
108
  'Vagrantfile',
109
109
  'Passenger.sublime-project',
110
110
  'Passenger.xcodeproj/**/*',
111
+ 'build/support/vendor/*/.*',
112
+ 'build/support/vendor/*/spec/**/*',
111
113
  'src/ruby_supportlib/phusion_passenger/vendor/*/.*',
112
114
  'src/ruby_supportlib/phusion_passenger/vendor/*/hacking/**/*',
113
115
  'src/ruby_supportlib/phusion_passenger/vendor/*/spec/**/*',
@@ -484,6 +484,12 @@ module PhusionPassenger
484
484
  end
485
485
  memoize :has_math_library?, true
486
486
 
487
+ def self.has_dl_library?
488
+ return try_link("Checking for -ldl support",
489
+ :c, "int main() { return 0; }\n", '-ldl')
490
+ end
491
+ memoize :has_dl_library?, true
492
+
487
493
  def self.has_alloca_h?
488
494
  return try_compile("Checking for alloca.h",
489
495
  :c, '#include <alloca.h>')
@@ -211,7 +211,7 @@ module PhusionPassenger
211
211
  end
212
212
  result << ' -lrt' if has_rt_library?
213
213
  result << ' -lmath' if has_math_library?
214
- result << ' -ldl'
214
+ result << ' -ldl' if has_dl_library?
215
215
  result.strip!
216
216
  return result
217
217
  end
@@ -1,5 +1,5 @@
1
1
  # Phusion Passenger - https://www.phusionpassenger.com/
2
- # Copyright (c) 2010-2015 Phusion Holding B.V.
2
+ # Copyright (c) 2010-2016 Phusion Holding B.V.
3
3
  #
4
4
  # "Passenger", "Phusion Passenger" and "Union Station" are registered
5
5
  # trademarks of Phusion Holding B.V.
@@ -67,7 +67,7 @@ module PhusionPassenger
67
67
  touch_temp_dir_in_background
68
68
  ########################
69
69
  ########################
70
- watch_log_files_in_background if should_watch_logs?
70
+ watch_log_files_in_background if should_watch_one_or_more_log_files?
71
71
  wait_until_engine_has_exited if should_wait_until_engine_has_exited?
72
72
  rescue Interrupt
73
73
  trapsafe_shutdown_and_cleanup(true)
@@ -456,15 +456,34 @@ module PhusionPassenger
456
456
  @threads << thread
457
457
  @interruptable_threads << thread
458
458
  end
459
- thread = Utils.create_thread_and_abort_on_exception do
460
- watch_log_file(@options[:log_file])
459
+ if should_watch_main_log_file?
460
+ thread = Utils.create_thread_and_abort_on_exception do
461
+ watch_log_file(@options[:log_file])
462
+ end
463
+ @threads << thread
464
+ @interruptable_threads << thread
461
465
  end
462
- @threads << thread
463
- @interruptable_threads << thread
464
466
  end
465
467
 
466
- def should_watch_logs?
467
- return !@options[:daemonize] && @options[:log_file] != "/dev/null"
468
+ def should_watch_one_or_more_log_files?
469
+ !@options[:daemonize]
470
+ end
471
+
472
+ def should_watch_main_log_file?
473
+ if @options[:daemonize]
474
+ false
475
+ else
476
+ begin
477
+ stat = File.stat(@options[:log_file])
478
+ rescue Errno::ENOENT
479
+ stat = nil
480
+ end
481
+ if stat
482
+ stat.file?
483
+ else
484
+ true
485
+ end
486
+ end
468
487
  end
469
488
 
470
489
  def should_wait_until_engine_has_exited?
@@ -1,5 +1,5 @@
1
1
  # daemon_controller, library for robust daemon management
2
- # Copyright (c) 2010-2015 Phusion
2
+ # Copyright (c) 2010-2016 Phusion Holding B.V.
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +22,7 @@
22
22
  require 'tempfile'
23
23
  require 'fcntl'
24
24
  require 'socket'
25
+ require 'pathname'
25
26
  require 'timeout'
26
27
  if Process.respond_to?(:spawn)
27
28
  require 'rbconfig'
@@ -560,7 +561,7 @@ private
560
561
  end
561
562
 
562
563
  def differences_in_log_file
563
- if @original_log_file_stat
564
+ if @original_log_file_stat && @original_log_file_stat.file?
564
565
  File.open(@log_file, 'r') do |f|
565
566
  f.seek(@original_log_file_stat.size, IO::SEEK_SET)
566
567
  diff = f.read.strip
@@ -596,6 +597,39 @@ private
596
597
  end
597
598
 
598
599
  def run_command(command)
600
+ if should_capture_output_while_running_command?
601
+ run_command_while_capturing_output(command)
602
+ else
603
+ run_command_without_capturing_output(command)
604
+ end
605
+ end
606
+
607
+ def should_capture_output_while_running_command?
608
+ if is_std_channel_chardev?(@log_file)
609
+ false
610
+ else
611
+ begin
612
+ real_log_file = Pathname.new(@log_file).realpath.to_s
613
+ rescue SystemCallError
614
+ real_log_file = nil
615
+ end
616
+ if real_log_file
617
+ !is_std_channel_chardev?(real_log_file)
618
+ else
619
+ true
620
+ end
621
+ end
622
+ end
623
+
624
+ def is_std_channel_chardev?(path)
625
+ path == "/dev/stdout" ||
626
+ path == "/dev/stderr" ||
627
+ path == "/dev/fd/1" ||
628
+ path == "/dev/fd/2" ||
629
+ path =~ %r(\A/proc/([0-9]+|self)/fd/[12]\Z)
630
+ end
631
+
632
+ def run_command_while_capturing_output(command)
599
633
  # Create tempfile for storing the command's output.
600
634
  tempfile = Tempfile.new('daemon-output')
601
635
  tempfile_path = tempfile.path
@@ -691,6 +725,90 @@ private
691
725
  File.unlink(tempfile_path) rescue nil
692
726
  end
693
727
 
728
+ def run_command_without_capturing_output(command)
729
+ if self.class.fork_supported? || self.class.spawn_supported?
730
+ if Process.respond_to?(:spawn)
731
+ options = {
732
+ :in => "/dev/null",
733
+ :out => :out,
734
+ :err => :err,
735
+ :close_others => true
736
+ }
737
+ @keep_ios.each do |io|
738
+ options[io] = io
739
+ end
740
+ if @daemonize_for_me
741
+ pid = Process.spawn(@env, ruby_interpreter, SPAWNER_FILE,
742
+ command, options)
743
+ else
744
+ pid = Process.spawn(@env, command, options)
745
+ end
746
+ else
747
+ pid = safe_fork(@daemonize_for_me) do
748
+ ObjectSpace.each_object(IO) do |obj|
749
+ if !@keep_ios.include?(obj)
750
+ obj.close rescue nil
751
+ end
752
+ end
753
+ STDIN.reopen("/dev/null", "r")
754
+ ENV.update(@env)
755
+ exec(command)
756
+ end
757
+ end
758
+
759
+ # run_command might be running in a timeout block (like
760
+ # in #start_without_locking).
761
+ begin
762
+ interruptable_waitpid(pid)
763
+ rescue Errno::ECHILD
764
+ # Maybe a background thread or whatever waitpid()'ed
765
+ # this child process before we had the chance. There's
766
+ # no way to obtain the exit status now. Assume that
767
+ # it started successfully; if it didn't we'll know
768
+ # that later by checking the PID file and by pinging
769
+ # it.
770
+ return
771
+ rescue Timeout::Error
772
+ daemonization_timed_out
773
+
774
+ # If the daemon doesn't fork into the background
775
+ # in time, then kill it.
776
+ begin
777
+ Process.kill('SIGTERM', pid)
778
+ rescue SystemCallError
779
+ end
780
+ begin
781
+ Timeout.timeout(5, Timeout::Error) do
782
+ begin
783
+ interruptable_waitpid(pid)
784
+ rescue SystemCallError
785
+ end
786
+ end
787
+ rescue Timeout::Error
788
+ begin
789
+ Process.kill('SIGKILL', pid)
790
+ interruptable_waitpid(pid)
791
+ rescue SystemCallError
792
+ end
793
+ end
794
+ raise DaemonizationTimeout
795
+ end
796
+ if $?.exitstatus != 0
797
+ raise StartError, "Daemon '#{@identifier}' failed to start."
798
+ end
799
+ else
800
+ if @env && !@env.empty?
801
+ raise "Setting the :env option is not supported on this Ruby implementation."
802
+ elsif @daemonize_for_me
803
+ raise "Setting the :daemonize_for_me option is not supported on this Ruby implementation."
804
+ end
805
+
806
+ if !system(command)
807
+ raise StartError, "Daemon '#{@identifier}' failed to start."
808
+ end
809
+ end
810
+ end
811
+
694
812
  def run_ping_command
695
813
  if @ping_command.respond_to?(:call)
696
814
  begin