passenger 4.0.50 → 4.0.51

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.

checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YjJhMzI2NDM1MTlhN2QwZDE5YmZjOTI1YTAwMWU5NjhmYjBlZTdmMg==
4
+ NjAyOTQ3MzJjNGQxYzczZmQ4MWFjZWVkMjAxYWZhYTliZWNjM2QzZg==
5
5
  data.tar.gz: !binary |-
6
- NTEwMzNiNWM5MDlkYWUyNzE3ZTZjNWM1YThlMjg0NmE0ZTEwMGViYQ==
6
+ MzcxYWNhMjI3YmZlMzQxOTU4ZWQ2ZTFhZTZkZGEyMWI5OTE3NzQzYg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZjkwMjhmNzExYzNlNzA5ZjQ5MzA2YTQzMjNlY2I0Zjc0OWU4ZDYzNjVlNzE5
10
- ZTg5NzBkZGY3NzU5NjU5ZTM0ZGM2MGU5YTg2ZjRjZmI1ZWM2MDBjNjg1ODUx
11
- ZTRjNzJiYTdkZDcwNzlmYTNmNmQxNDQ0ODk3OTc0ODA1MDJiNzk=
9
+ NGQ2OTMyNTc5NmRhMDI5MDgzNWQ3NWU3MDZkNDM3NWQxODdhYzliNjJiZTdl
10
+ ZWVhZWU2NmI5ZTdlYTY0YjRhOGZmMDAxNzBjZWRjZGFiMzcyODEyNTg3ZWFj
11
+ ZTkxMGNhNjg0MmMyOTcxNmI2MTM1ZjQ2NmU5YTcxNWU0ODU1ZWY=
12
12
  data.tar.gz: !binary |-
13
- YzYzOTVhOWVhNTYwY2FiMDU5YTA3NzFjYWJiMjQ3MmVhNmJjNmI5NDQ3ZDY5
14
- M2U2OGRmZTA4NzllYmMzN2RkM2RkOWRiZmE5ZDM0MjJhYmQ0ODg5NmYxNWFj
15
- OWM1YWQ2Mjg2OTVmZDY4ZTdhZmI5YmJlMGVkNDUzNzgyZTlmZTU=
13
+ MDY3NGZiYzA2ZmY0MmZkOTJjMmFiYjc4ZjRiMmQ5YzkxNjU2MDU3OGI3NzVh
14
+ MGE3MTNiMDYwZWI5YmQ1NjNhOGRhZTE1YWVjYTdjZWE5ZjNlYWI3YjBhNmU5
15
+ YzRkYzIxNWVjMjI0NGJhN2I1YTJmNzhkMzU5YjQ2NzM0MWIxNTU=
@@ -2,11 +2,11 @@
2
2
  Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
3
3
  Comment: GPGTools - http://gpgtools.org
4
4
 
5
- iQEcBAABAgAGBQJT/ac4AAoJECrHRaUKISqMyBQIAI3940hdxJ7dL8kC+He5qLhk
6
- RCpmZBZhmANL97OOVslpi3ZSMDE4lUsvn/oPD0T+zO1doaoxsus1CFaorT1vfzB9
7
- 30MEMVXWUMMQ22aWSsWyTmtPL+0HUMRlAmVvgUFW8m27//irl8sIBXA2cFiIHhk+
8
- 8b1OV1wlr6UEkqXmw2XKTyb6+rH9nU3Qhj1VZKsg/7kDCp9R7rNgxn7MuK0+JRUD
9
- BfDmuovFnkhj+XssXbBGiTg1+n7/Ywie23uY+tmGNKE84S5ZA593BwJPJ8CzahHf
10
- MKXpCKbr8fWA841sr/4M5BgoCiu4K+5b9VMwvU/K4YMR+pxk+doze9/rBoJara8=
11
- =/3iD
5
+ iQEcBAABAgAGBQJUIqZfAAoJECrHRaUKISqMSdwH/isfT389hMGZxdtsYMVsPjEt
6
+ Xzz1Kb9FdcDjfTofJftUKvHA8Hb2GLSbzAFUfrkZ3RH8uMbi0BabTC+lCigVbD/w
7
+ wD+es6VaTsbuWKB5ZnM3tLPUXqq8x+q1iaqQPfaR4CFRkKHjjyjx37eHv5T5jSRZ
8
+ ByGpcK9+EJrgVnDNFrNfasK4HftWAuNJx628V0Lg41Z85NbymUeJSZRBzCbT8NZE
9
+ gVpxc1XzrHTgCKfeEDiRFdAi1vg4t2/KoL5lqMtDtSbb0p/Mmnx4b9drGjHVWYY+
10
+ CbpjTVxFnEaWm57ph0y9kzOyHJpCoRvBiUsxUqs+rOi8WIrDXoFcEmGV5IO7VuA=
11
+ =UqIJ
12
12
  -----END PGP SIGNATURE-----
data.tar.gz.asc CHANGED
@@ -2,11 +2,11 @@
2
2
  Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
3
3
  Comment: GPGTools - http://gpgtools.org
4
4
 
5
- iQEcBAABAgAGBQJT/ac4AAoJECrHRaUKISqMrpEH/126KVkt90cVfXkzNBSB7GxI
6
- sMCmJK4iHgiTo8QDckXWXYqTGzlYvVN+90vw16aXJQadq4LZ7KEe3Nzon33ljR64
7
- sJLak3Yiucr+y9QFJaHzfIegD0eZID2nFRxLpUebzsEZlmfpwa9oSkezacCGupEO
8
- asIRMbNoEgzn4FXB9sGfNTCfVCz/xLVL2527BpZh2T/7kvyib6XtCUpW9uAQG94U
9
- 9L1iOpKXST/gADAnYjJtTSG2TmF/rjqczDy9KgzJsTpFTImZL44ZLNw+wVvzKynt
10
- GvvBNSXPL3OtAN0Cbh6+fSEP6O7pp9qtMd+KKZONY8Y3jyUb9evYprxeXucYh2A=
11
- =7wtl
5
+ iQEcBAABAgAGBQJUIqZfAAoJECrHRaUKISqMXh4IAI+HkapDaCYEng9NQJ/pN/+D
6
+ 4tvtP587LbTtXjefnwWOCABt/hpnMIrwMqYVSr+PpzFaKkUUduC5OOjeIj61Qcwv
7
+ W3Ozpgc3S6o0mml3fRaT1duXGVA8raR4d1+Qc9hx7miMy1CVV9EzY6u8uIc4bfiA
8
+ O4dh1i8h4qp6XMRBgGciw/st9VykiclUkZWKmQQdvNQRRfhAkhBcOMOMg6J9ElOO
9
+ SAlkH1/hMQtt1QXkML9fJK94atBovyWcmX9TwV6UyWOECfpNAS6iLZ9kWZHcCSjz
10
+ qTgaCna1TXBaAxGmYXXsYdKx+YUuix4WHOBNPjiJ6JmZV8XemoI1AgJBbJKDj2A=
11
+ =Z4ow
12
12
  -----END PGP SIGNATURE-----
data/CHANGELOG CHANGED
@@ -1,3 +1,16 @@
1
+ Release 4.0.51
2
+ --------------
3
+
4
+ * Fixed a null termination bug when autodetecting application types.
5
+ * Node.js apps can now also trigger the inverse port binding mechanism by passing `'/passenger'` as argument. This was introduced in order to be able to support the Hapi.js framework. Please read http://stackoverflow.com/questions/20645231/phusion-passenger-error-http-server-listen-was-called-more-than-once/20645549 for more information regarding Hapi.js support.
6
+ * It is now possible to abort Node.js WebSocket connections upon application restart. Please refer to https://github.com/phusion/passenger/wiki/Phusion-Passenger:-Node.js-tutorial#restarting_apps_that_serve_long_running_connections for more information. Closes GH-1200.
7
+ * Passenger Standalone no longer automatically resolves symlinks in its paths.
8
+ * `passenger-config system-metrics` no longer crashes when the system clock is set to a time in the past. Closes GH-1276.
9
+ * `passenger-status`, `passenger-memory-stats`, `passenger-install-apache2-module` and `passenger-install-nginx-module` no longer output ANSI color codes by default when STDOUT is not a TTY. Closes GH-487.
10
+ * `passenger-install-nginx-module --auto` is now all that's necessary to make it fully non-interactive. It is no longer necessary to provide all the answers through command line parameters. Closes GH-852.
11
+ * Minor contribution by Alessandro Lenzen.
12
+
13
+
1
14
  Release 4.0.50
2
15
  --------------
3
16
 
@@ -1,5 +1,6 @@
1
1
  _why
2
2
  Adam Duke
3
+ Alessandro Lenzen
3
4
  Alex Osborne
4
5
  Alex Tomlins
5
6
  Aman Gupta
@@ -31,7 +32,9 @@ Hongli Lai (Phusion)
31
32
  Ian Ehlert
32
33
  isaac
33
34
  Isaac Reuben
35
+ J Smith
34
36
  J.W. Koelewijn
37
+ Jacob Elder
35
38
  Jacob Harris
36
39
  James Miller
37
40
  Jan Berkel
@@ -843,6 +843,9 @@ parser = OptionParser.new do |opts|
843
843
  # "#{indent}create backups of the existing files.") do
844
844
  # options[:backup_config] = false
845
845
  #end
846
+ opts.on("--force-colors", "Display colors even if stdout is not a TTY") do
847
+ options[:colorize] = true
848
+ end
846
849
  opts.on("--snippet", "Show just the Apache config snippet.") do
847
850
  options[:snippet] = true
848
851
  end
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # Phusion Passenger - https://www.phusionpassenger.com/
3
- # Copyright (c) 2010-2013 Phusion
3
+ # Copyright (c) 2010-2014 Phusion
4
4
  #
5
5
  # "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
6
  #
@@ -241,6 +241,9 @@ private
241
241
  elsif @nginx_source_dir
242
242
  puts "<b>=> Proceeding with choice 2.</b>"
243
243
  return false
244
+ elsif @auto
245
+ puts "<b>=> Proceeding with choice 1.</b>"
246
+ return true
244
247
  else
245
248
  choice = prompt("Enter your choice (1 or 2) or press Ctrl-C to abort") do |input|
246
249
  if input == "1" || input == "2"
@@ -337,6 +340,9 @@ private
337
340
  if @prefix
338
341
  puts "<b>=> #{@prefix}</b>"
339
342
  return @prefix
343
+ elsif @auto
344
+ puts "<b>=> /opt/nginx</b>"
345
+ return "/opt/nginx"
340
346
  else
341
347
  prefix = prompt("Please specify a prefix directory [/opt/nginx]") do |input|
342
348
  if input.empty? || input =~ %r(/)
@@ -414,6 +420,9 @@ private
414
420
  puts "<b>=> #{extra_args}</b>"
415
421
  end
416
422
  return extra_args
423
+ elsif @auto
424
+ puts "<b>=> No extra configure flags.</b>"
425
+ return ""
417
426
  else
418
427
  extra_args = prompt "Extra arguments to pass to configure script"
419
428
 
@@ -624,6 +633,9 @@ parser = OptionParser.new do |opts|
624
633
  "#{indent}'ruby,python,nodejs,meteor')") do |value|
625
634
  options[:languages] = value.split(",")
626
635
  end
636
+ opts.on("--force-colors", "Display colors even if stdout is not a TTY") do
637
+ options[:colorize] = true
638
+ end
627
639
  end
628
640
  begin
629
641
  parser.parse!
@@ -36,21 +36,16 @@ PhusionPassenger.locate_directories
36
36
  PhusionPassenger.require_passenger_lib 'platform_info'
37
37
  PhusionPassenger.require_passenger_lib 'platform_info/ruby'
38
38
  PhusionPassenger.require_passenger_lib 'admin_tools/memory_stats'
39
+ PhusionPassenger.require_passenger_lib 'utils/ansi_colors'
39
40
 
40
41
  include PhusionPassenger
41
42
 
42
- # ANSI color codes
43
- RESET = "\e[0m"
44
- BOLD = "\e[1m"
45
- WHITE = "\e[37m"
46
- YELLOW = "\e[33m"
47
- BLUE_BG = "\e[44m"
48
-
49
43
  # Container for tabular data.
50
44
  class Table
51
- def initialize(column_names)
45
+ def initialize(column_names, colors)
52
46
  @column_names = column_names
53
47
  @rows = []
48
+ @colors = colors
54
49
  end
55
50
 
56
51
  def add_row(values)
@@ -90,19 +85,19 @@ class Table
90
85
  left_bar_size = free_space / 2
91
86
  right_bar_size = free_space - left_bar_size
92
87
  end
93
- result = "#{BLUE_BG}#{BOLD}#{YELLOW}\n"
88
+ result = "#{@colors.blue_bg}#{@colors.bold}#{@colors.yellow}\n"
94
89
  result << "#{"-" * left_bar_size} #{title} #{"-" * right_bar_size}\n"
95
90
  if !@rows.empty?
96
- result << WHITE
91
+ result << @colors.white
97
92
  result << header
98
93
  end
99
94
  else
100
95
  result = header.dup
101
96
  end
102
97
  if @rows.empty?
103
- result << RESET
98
+ result << @colors.reset
104
99
  else
105
- result << ("-" * header.size) << "#{RESET}\n"
100
+ result << ("-" * header.size) << "#{@colors.reset}\n"
106
101
  @rows.each do |row|
107
102
  result << sprintf(format_string, *row).rstrip << "\n"
108
103
  end
@@ -114,6 +109,7 @@ end
114
109
  class App
115
110
  def initialize
116
111
  @stats = AdminTools::MemoryStats.new
112
+ @colors = Utils::AnsiColors.new
117
113
  end
118
114
 
119
115
  def start
@@ -122,7 +118,7 @@ class App
122
118
  if @stats.apache_processes
123
119
  print_process_list("Apache processes", @stats.apache_processes)
124
120
  else
125
- puts "#{BLUE_BG}#{BOLD}#{YELLOW}------------- Apache processes -------------#{RESET}\n"
121
+ puts "#{@colors.blue_bg}#{@colors.bold}#{@colors.yellow}------------- Apache processes -------------#{@colors.reset}\n"
126
122
  STDERR.puts "*** WARNING: The Apache executable cannot be found."
127
123
  STDERR.puts "Please set the APXS2 environment variable to your 'apxs2' " <<
128
124
  "executable's filename, or set the HTTPD environment variable " <<
@@ -138,14 +134,14 @@ class App
138
134
  if @stats.platform_provides_private_dirty_rss_information? &&
139
135
  Process.euid != 0 &&
140
136
  @stats.root_privileges_required_for_private_dirty_rss?
141
- puts "*** WARNING: Please run this tool with #{BOLD}#{PlatformInfo.ruby_sudo_command}#{RESET}. Otherwise the " <<
137
+ puts "*** WARNING: Please run this tool with #{@colors.bold}#{PlatformInfo.ruby_sudo_command}#{@colors.reset}. Otherwise the " <<
142
138
  "private dirty RSS (a reliable metric for real memory usage) of processes cannot be determined."
143
139
  end
144
140
  end
145
141
 
146
142
  private
147
143
  def print_process_list(title, processes, options = {})
148
- table = Table.new(%w{PID PPID VMSize Private Resident Name})
144
+ table = Table.new(%w{PID PPID VMSize Private Resident Name}, @colors)
149
145
  table.add_rows(processes)
150
146
  if options.has_key?(:show_ppid) && !options[:show_ppid]
151
147
  table.remove_column('PPID')
@@ -41,7 +41,7 @@ require 'optparse'
41
41
  include PhusionPassenger::AdminTools
42
42
  include PhusionPassenger::Utils::AnsiColors
43
43
 
44
- DEFAULT_OPTIONS = { :show => 'pool' }.freeze
44
+ DEFAULT_OPTIONS = { :show => 'pool', :color => STDOUT.tty? }.freeze
45
45
 
46
46
 
47
47
  ##### Show status command #####
@@ -93,7 +93,7 @@ def show_status(server_instance, options)
93
93
  when 'pool'
94
94
  client = server_instance.connect(:role => :passenger_status)
95
95
  begin
96
- puts client.pool_status(:verbose => options[:verbose], :colorize => true)
96
+ puts client.pool_status(:verbose => options[:verbose], :colorize => options[:color])
97
97
  rescue SystemCallError => e
98
98
  STDERR.puts "*** ERROR: Cannot query status for Phusion Passenger instance #{server_instance.pid}:"
99
99
  STDERR.puts e.to_s
@@ -231,6 +231,9 @@ def create_option_parser(options)
231
231
  options[:show] = what
232
232
  end
233
233
  end
234
+ opts.on("--force-colors", "Display colors even if stdout is not a TTY") do
235
+ options[:color] = true
236
+ end
234
237
  opts.on("--verbose", "-v", "Show verbose information.") do
235
238
  options[:verbose] = true
236
239
  end
@@ -1705,7 +1705,7 @@ to implement it like that:
1705
1705
  which web applications to pre-start. It's probably not completely impossible
1706
1706
  to obtain such a list, but this brings us to the following point;
1707
1707
  - Users expect things like 'mod_env' to work even in combination with Phusion
1708
- Passenger. For example some people put ``SetEnv PATH=....'' in their virtual
1708
+ Passenger. For example some people put ``SetEnv PATH ....'' in their virtual
1709
1709
  host block and they expect the web application to pick that environment variable
1710
1710
  up when it's started. Information like this is stored in module-specific
1711
1711
  locations that Phusion Passenger cannot access directly. Even if the previous
@@ -230,13 +230,15 @@
230
230
 
231
231
  8.6.8. passenger_pass_header <header name> => passenger-pass-header-header-name--1cg31je
232
232
 
233
- 8.6.9. passenger_buffer_response <on|off> => passenger-buffer-response
233
+ 8.6.9. passenger_ignore_headers <header names…> => passenger-ignore-headers-header-names--12zg5oh
234
234
 
235
- 8.6.10. passenger_buffer_size => passenger-buffer-size-1jfkq87
235
+ 8.6.10. passenger_buffer_response <on|off> => passenger-buffer-response
236
236
 
237
- 8.6.11. passenger_buffers => passenger-busy-buffers
237
+ 8.6.11. passenger_buffer_size => passenger-buffer-size-1jfkq87
238
238
 
239
- 8.6.12. passenger_busy_buffer_size => passenger-busy-buffer-size-124sj61
239
+ 8.6.12. passenger_buffers => passenger-busy-buffers
240
+
241
+ 8.6.13. passenger_busy_buffer_size => passenger-busy-buffer-size-124sj61
240
242
 
241
243
  8.7. Logging and debugging options => logging-and-debugging-options-14e91ni
242
244
 
@@ -1854,6 +1854,16 @@ location / {
1854
1854
  }
1855
1855
  ------------------------------
1856
1856
 
1857
+ This option may occur in the following places:
1858
+
1859
+ * In the 'http' configuration block.
1860
+ * In a 'server' configuration block.
1861
+ * In a 'location' configuration block.
1862
+ * In an 'if' configuration scope.
1863
+
1864
+ ==== passenger_ignore_headers <header names...> ====
1865
+ Disables processing of certain response header fields from the application, similar to how 'proxy_ignore_headers' works.
1866
+
1857
1867
  This option may occur in the following places:
1858
1868
 
1859
1869
  * In the 'http' configuration block.
@@ -107,6 +107,7 @@ private:
107
107
  pos = appendData(pos, end, appRoot);
108
108
  pos = appendData(pos, end, "/");
109
109
  pos = appendData(pos, end, name);
110
+ pos = appendData(pos, end, "\0", 1);
110
111
  if (OXT_UNLIKELY(pos == end)) {
111
112
  TRACE_POINT();
112
113
  throw RuntimeException("Not enough buffer space");
@@ -1205,6 +1205,16 @@ protected:
1205
1205
  fflush(stderr);
1206
1206
  _exit(1);
1207
1207
  }
1208
+
1209
+ ret = chdir("/");
1210
+ if (ret == -1) {
1211
+ int e = errno;
1212
+ fprintf(stderr, "Cannot chdir(\"/\") inside chroot: %s (errno=%d)\n",
1213
+ strerror(e),
1214
+ e);
1215
+ fflush(stderr);
1216
+ _exit(1);
1217
+ }
1208
1218
  }
1209
1219
  }
1210
1220
 
@@ -90,7 +90,7 @@
90
90
 
91
91
  #define NGINX_DOC_URL "https://www.phusionpassenger.com/documentation/Users%20guide%20Nginx.html"
92
92
 
93
- #define PASSENGER_VERSION "4.0.50"
93
+ #define PASSENGER_VERSION "4.0.51"
94
94
 
95
95
  #define POOL_HELPER_THREAD_STACK_SIZE 262144
96
96
 
@@ -24,6 +24,7 @@
24
24
  */
25
25
  #include <iomanip>
26
26
  #include <cstdlib>
27
+ #include <cstring>
27
28
  #include <fcntl.h>
28
29
  #include <unistd.h>
29
30
  #include <Logging.h>
@@ -36,6 +37,7 @@ namespace Passenger {
36
37
  int _logLevel = 0;
37
38
  int _logOutput = STDERR_FILENO;
38
39
  static bool printAppOutputAsDebuggingMessages = false;
40
+ AssertionFailureInfo lastAssertionFailure;
39
41
 
40
42
  int
41
43
  getLogLevel() {
@@ -108,6 +110,15 @@ _writeLogEntry(const std::string &str) {
108
110
  _writeLogEntry(StaticString(str));
109
111
  }
110
112
 
113
+ const char *
114
+ _strdupStringStream(const std::stringstream &stream) {
115
+ string str = stream.str();
116
+ char *buf = (char *) malloc(str.size() + 1);
117
+ memcpy(buf, str.data(), str.size());
118
+ buf[str.size()] = '\0';
119
+ return buf;
120
+ }
121
+
111
122
  static void
112
123
  realPrintAppOutput(char *buf, unsigned int bufSize,
113
124
  const char *pidStr, unsigned int pidStrLen,
@@ -56,14 +56,25 @@ using namespace oxt;
56
56
 
57
57
  /********** Debug logging facilities **********/
58
58
 
59
+ struct AssertionFailureInfo {
60
+ const char *filename;
61
+ const char *function; // May be NULL.
62
+ const char *expression;
63
+ unsigned int line;
64
+ };
65
+
59
66
  extern int _logLevel;
60
67
  extern int _logOutput;
61
68
 
69
+ // If assert() or similar fails, we attempt to store its information here.
70
+ extern AssertionFailureInfo lastAssertionFailure;
71
+
62
72
  int getLogLevel();
63
73
  void setLogLevel(int value);
64
74
  bool setDebugFile(const char *logFile = NULL);
65
75
  void _prepareLogEntry(std::stringstream &sstream, const char *file, unsigned int line);
66
76
  void _writeLogEntry(const std::string &str);
77
+ const char *_strdupStringStream(const std::stringstream &stream);
67
78
 
68
79
 
69
80
  enum PassengerLogLevel {
@@ -145,22 +156,44 @@ void printAppOutput(pid_t pid, const char *channelName, const char *message, uns
145
156
  */
146
157
  void setPrintAppOutputAsDebuggingMessages(bool enabled);
147
158
 
148
-
149
159
  /** Print a [BUG] error message and abort with a stack trace. */
150
160
  #define P_BUG(expr) \
151
161
  do { \
152
162
  TRACE_POINT(); \
153
- P_CRITICAL("[BUG] " << expr); \
163
+ const char *_exprStr; \
164
+ std::stringstream sstream; \
165
+ sstream << expr; \
166
+ _exprStr = Passenger::_strdupStringStream(sstream); \
167
+ Passenger::lastAssertionFailure.filename = __FILE__; \
168
+ Passenger::lastAssertionFailure.line = __LINE__; \
169
+ Passenger::lastAssertionFailure.function = __PRETTY_FUNCTION__; \
170
+ Passenger::lastAssertionFailure.expression = _exprStr; \
171
+ P_CRITICAL("[BUG] " << _exprStr); \
154
172
  abort(); \
155
173
  } while (false)
156
174
 
157
175
  #define P_BUG_UTP(expr) \
158
176
  do { \
159
177
  UPDATE_TRACE_POINT(); \
160
- P_CRITICAL("[BUG] " << expr); \
178
+ const char *_exprStr; \
179
+ std::stringstream sstream; \
180
+ sstream << expr; \
181
+ _exprStr = Passenger::_strdupStringStream(sstream); \
182
+ Passenger::lastAssertionFailure.filename = __FILE__; \
183
+ Passenger::lastAssertionFailure.line = __LINE__; \
184
+ Passenger::lastAssertionFailure.function = __PRETTY_FUNCTION__; \
185
+ Passenger::lastAssertionFailure.expression = _exprStr; \
186
+ P_CRITICAL("[BUG] " << _exprStr); \
161
187
  abort(); \
162
188
  } while (false)
163
189
 
190
+ #define P_ASSERT_EQ(value, expected) \
191
+ do { \
192
+ if (OXT_UNLIKELY(value != expected)) { \
193
+ P_BUG("Expected " << #value << " to be " << expected << ", got " << value); \
194
+ } \
195
+ } while (false)
196
+
164
197
 
165
198
  class NotExpectingExceptions {
166
199
  private:
@@ -156,6 +156,14 @@ private:
156
156
  }
157
157
  }
158
158
 
159
+ void resetOnClockSkew(unsigned long long timestamp) {
160
+ if (getLastSample().timestamp > timestamp) {
161
+ for (unsigned int i = 0; i < maxSamples; i++) {
162
+ samples[i] = Sample();
163
+ }
164
+ }
165
+ }
166
+
159
167
  public:
160
168
  SpeedMeter()
161
169
  : start(0),
@@ -168,8 +176,7 @@ public:
168
176
  }
169
177
 
170
178
  const Sample &lastSample = getLastSample();
171
- // Timestamp must be larger than that of previous sample.
172
- assert(lastSample.timestamp <= timestamp);
179
+ resetOnClockSkew(timestamp);
173
180
 
174
181
  if (lastSample.timestamp <= timestamp - minAge) {
175
182
  Sample &nextSample = samples[(start + count) % maxSamples];
@@ -235,7 +242,7 @@ public:
235
242
  return numeric_limits<ValueType>::max();
236
243
  }
237
244
 
238
- #if 1
245
+ #if 0
239
246
  void debug() const {
240
247
  const unsigned long long timeThreshold = getTimeThreshold();
241
248
 
@@ -121,14 +121,6 @@ static void *customDiagnosticsDumperUserData;
121
121
  static int emergencyPipe1[2] = { -1, -1 };
122
122
  static int emergencyPipe2[2] = { -1, -1 };
123
123
 
124
- // If assert() failed, its information is stored here.
125
- static struct {
126
- const char *filename;
127
- const char *function; // May be NULL.
128
- const char *expression;
129
- unsigned int line;
130
- } lastAssertionFailure;
131
-
132
124
 
133
125
  static void
134
126
  ignoreSigpipe() {
@@ -29,6 +29,7 @@ var os = require('os');
29
29
  var fs = require('fs');
30
30
  var net = require('net');
31
31
  var http = require('http');
32
+ var util = require('util');
32
33
 
33
34
  var LineReader = require('phusion_passenger/line_reader').LineReader;
34
35
 
@@ -197,7 +198,7 @@ function installServer() {
197
198
  server.originalListen(socketPath, function() {
198
199
  server.removeListener('error', errorHandler);
199
200
  doneListening(callback);
200
- process.nextTick(finalizeStartup);
201
+ process.nextTick(installControlServer);
201
202
  });
202
203
  }
203
204
 
@@ -221,7 +222,7 @@ function installServer() {
221
222
  }
222
223
 
223
224
  function listenAndMaybeInstall(port) {
224
- if (port === 'passenger') {
225
+ if (port === 'passenger' || port == '/passenger') {
225
226
  if (!PhusionPassenger._appInstalled) {
226
227
  return installServer.apply(this, arguments);
227
228
  } else {
@@ -232,20 +233,112 @@ function listenAndMaybeInstall(port) {
232
233
  }
233
234
  }
234
235
 
236
+ function installControlServer() {
237
+ var server = net.createServer(onNewClient);
238
+ var listenTries = 0;
239
+
240
+ doListen();
241
+
242
+ function onNewClient(client) {
243
+ client.on('error', function(e) {
244
+ console.trace(e);
245
+ });
246
+ readNextMessageHeader(client);
247
+ }
248
+
249
+ function readNextMessageHeader(client) {
250
+ client.once('readable', onReadable);
251
+
252
+ function onReadable() {
253
+ var size = client.read(2);
254
+ if (size !== null) {
255
+ readNextMessageBody(client, size.readUInt16BE(0));
256
+ } else {
257
+ client.once('readable', onReadable);
258
+ }
259
+ }
260
+ }
261
+
262
+ function readNextMessageBody(client, size) {
263
+ client.once('readable', onReadable);
264
+
265
+ function onReadable() {
266
+ var body = client.read(size);
267
+ if (body !== null) {
268
+ var args = body.toString('binary').split("\0");
269
+ args.pop();
270
+ handleMessage(client, args);
271
+ } else {
272
+ client.once('readable', onReadable);
273
+ }
274
+ }
275
+ }
276
+
277
+ function handleMessage(client, args) {
278
+ if (args[0] == 'abort_long_running_connections') {
279
+ shutdown();
280
+ client.end();
281
+ } else {
282
+ console.error("Invalid control message: " + util.inspect(args));
283
+ readNextMessageHeader(client);
284
+ }
285
+ }
286
+
287
+ function doListen() {
288
+ function errorHandler(error) {
289
+ if (error.errno == 'EADDRINUSE') {
290
+ if (listenTries == 100) {
291
+ server.emit('error', new Error(
292
+ 'Phusion Passenger could not find suitable socket address to bind the control server on'));
293
+ } else {
294
+ // Try again with another socket path.
295
+ listenTries++;
296
+ doListen();
297
+ }
298
+ } else {
299
+ server.emit('error', error);
300
+ }
301
+ }
302
+
303
+ var socketPath = PhusionPassenger.options.control_socket_path =
304
+ generateServerSocketPath();
305
+ server.once('error', errorHandler);
306
+ server.listen(socketPath, function() {
307
+ server.removeListener('error', errorHandler);
308
+ process.nextTick(finalizeStartup);
309
+ });
310
+ }
311
+ }
312
+
235
313
  function finalizeStartup() {
236
314
  process.stdout.write("!> Ready\n");
237
315
  process.stdout.write("!> socket: main;unix:" +
238
316
  PhusionPassenger._server.address() +
239
317
  ";http_session;0\n");
318
+ if (process.env['_PASSENGER_NODE_CONTROL_SERVER']) {
319
+ process.stdout.write("!> socket: control;unix:" +
320
+ PhusionPassenger.options.control_socket_path +
321
+ ";control;0\n");
322
+ }
240
323
  process.stdout.write("!> \n");
241
324
  }
242
325
 
243
326
  function shutdown() {
327
+ if (PhusionPassenger.shutting_down) {
328
+ return;
329
+ }
330
+
331
+ PhusionPassenger.shutting_down = true;
244
332
  try {
245
333
  fs.unlinkSync(PhusionPassenger.options.socket_path);
246
334
  } catch (e) {
247
335
  // Ignore error.
248
336
  }
337
+ try {
338
+ fs.unlinkSync(PhusionPassenger.options.control_socket_path);
339
+ } catch (e) {
340
+ // Ignore error.
341
+ }
249
342
  if (PhusionPassenger.listeners('exit').length == 0) {
250
343
  process.exit(0);
251
344
  } else {
@@ -30,7 +30,7 @@ module PhusionPassenger
30
30
 
31
31
  PACKAGE_NAME = 'passenger'
32
32
  # Run 'rake ext/common/Constants.h' after changing this number.
33
- VERSION_STRING = '4.0.50'
33
+ VERSION_STRING = '4.0.51'
34
34
 
35
35
  PREFERRED_NGINX_VERSION = '1.6.1'
36
36
  NGINX_SHA256_CHECKSUM = 'f5cfe682a1aeef4602c2ca705402d5049b748f946563f41d8256c18674836067'
@@ -1,5 +1,5 @@
1
1
  # Phusion Passenger - https://www.phusionpassenger.com/
2
- # Copyright (c) 2010-2013 Phusion
2
+ # Copyright (c) 2010-2014 Phusion
3
3
  #
4
4
  # "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
5
5
  #
@@ -60,11 +60,12 @@ class AbstractInstaller
60
60
  @stdout = STDOUT
61
61
  @stderr = STDERR
62
62
  @auto = !STDIN.tty?
63
+ @colors = Utils::AnsiColors.new(options[:colorize] || :auto)
63
64
  options.each_pair do |key, value|
64
65
  instance_variable_set(:"@#{key}", value)
65
66
  end
66
67
  end
67
-
68
+
68
69
  # Start the installation by calling the #install! method.
69
70
  def run
70
71
  before_install
@@ -91,11 +92,11 @@ class AbstractInstaller
91
92
  protected
92
93
  class Abort < StandardError
93
94
  end
94
-
95
+
95
96
  class CommandError < Abort
96
97
  end
97
-
98
-
98
+
99
+
99
100
  def interactive?
100
101
  return !@auto
101
102
  end
@@ -103,18 +104,18 @@ protected
103
104
  def non_interactive?
104
105
  return !interactive?
105
106
  end
106
-
107
-
107
+
108
+
108
109
  def before_install
109
110
  if STDOUT.respond_to?(:set_encoding)
110
111
  STDOUT.set_encoding("UTF-8")
111
112
  end
112
- STDOUT.write(Utils::AnsiColors::DEFAULT_TERMINAL_COLOR)
113
+ STDOUT.write(@colors.default_terminal_color)
113
114
  STDOUT.flush
114
115
  end
115
-
116
+
116
117
  def after_install
117
- STDOUT.write(Utils::AnsiColors::RESET)
118
+ STDOUT.write(@colors.reset)
118
119
  STDOUT.flush
119
120
  end
120
121
 
@@ -125,16 +126,16 @@ protected
125
126
  def users_guide_url
126
127
  return INDEX_DOC_URL
127
128
  end
128
-
129
+
129
130
  def dependencies
130
131
  return [[], []]
131
132
  end
132
-
133
+
133
134
  def check_dependencies(show_new_screen = true)
134
135
  new_screen if show_new_screen
135
136
  puts "<banner>Checking for required software...</banner>"
136
137
  puts
137
-
138
+
138
139
  PhusionPassenger.require_passenger_lib 'platform_info/depcheck'
139
140
  specs, ids = dependencies
140
141
  runner = PlatformInfo::Depcheck::ConsoleRunner.new
@@ -267,8 +268,8 @@ protected
267
268
  raise e
268
269
  end
269
270
  end
270
-
271
-
271
+
272
+
272
273
  def use_stderr
273
274
  old_stdout = @stdout
274
275
  begin
@@ -278,15 +279,15 @@ protected
278
279
  @stdout = old_stdout
279
280
  end
280
281
  end
281
-
282
+
282
283
  def print(text)
283
- @stdout.write(Utils::AnsiColors.ansi_colorize(text))
284
+ @stdout.write(@colors.ansi_colorize(text))
284
285
  @stdout.flush
285
286
  end
286
-
287
+
287
288
  def puts(text = nil)
288
289
  if text
289
- @stdout.puts(Utils::AnsiColors.ansi_colorize(text.to_s))
290
+ @stdout.puts(@colors.ansi_colorize(text.to_s))
290
291
  else
291
292
  @stdout.puts
292
293
  end
@@ -294,34 +295,35 @@ protected
294
295
  end
295
296
 
296
297
  def puts_error(text)
297
- @stderr.puts(Utils::AnsiColors.ansi_colorize("<red>#{text}</red>"))
298
+ @stderr.puts(@colors.ansi_colorize("<red>#{text}</red>"))
298
299
  @stderr.flush
299
300
  end
300
-
301
+
301
302
  def render_template(name, options = {})
303
+ options.merge!(:colors => @colors)
302
304
  puts ConsoleTextTemplate.new({ :file => name }, options).result
303
305
  end
304
-
306
+
305
307
  def new_screen
306
308
  puts
307
309
  line
308
310
  puts
309
311
  end
310
-
312
+
311
313
  def line
312
314
  puts "--------------------------------------------"
313
315
  end
314
-
316
+
315
317
  def prompt(message, default_value = nil)
316
318
  done = false
317
319
  while !done
318
320
  print "#{message}: "
319
-
321
+
320
322
  if non_interactive? && default_value
321
323
  puts default_value
322
324
  return default_value
323
325
  end
324
-
326
+
325
327
  begin
326
328
  result = STDIN.readline
327
329
  rescue EOFError
@@ -343,7 +345,7 @@ protected
343
345
  rescue Interrupt
344
346
  raise Abort
345
347
  end
346
-
348
+
347
349
  def prompt_confirmation(message)
348
350
  result = prompt("#{message} [y/n]") do |value|
349
351
  if value.downcase == 'y' || value.downcase == 'n'
@@ -380,8 +382,8 @@ protected
380
382
  def home_dir
381
383
  Etc.getpwuid(Process.uid).dir
382
384
  end
383
-
384
-
385
+
386
+
385
387
  def sh(*args)
386
388
  puts "# #{args.join(' ')}"
387
389
  result = system(*args)
@@ -393,14 +395,14 @@ protected
393
395
  return false
394
396
  end
395
397
  end
396
-
398
+
397
399
  def sh!(*args)
398
400
  if !sh(*args)
399
401
  puts_error "*** Command failed: #{args.join(' ')}"
400
402
  raise CommandError
401
403
  end
402
404
  end
403
-
405
+
404
406
  def rake(*args)
405
407
  PhusionPassenger.require_passenger_lib 'platform_info/ruby'
406
408
  if !PlatformInfo.rake_command
@@ -418,7 +420,7 @@ protected
418
420
  end
419
421
  sh!("#{PlatformInfo.rake_command} #{args.join(' ')}")
420
422
  end
421
-
423
+
422
424
  def download(url, output, options = {})
423
425
  options[:logger] ||= begin
424
426
  logger = Logger.new(STDOUT)
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
  # Phusion Passenger - https://www.phusionpassenger.com/
3
- # Copyright (c) 2010-2013 Phusion
3
+ # Copyright (c) 2010-2014 Phusion
4
4
  #
5
5
  # "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
6
  #
@@ -36,19 +36,20 @@ class ConsoleTextTemplate
36
36
  else
37
37
  data = input[:text]
38
38
  end
39
- @template = ERB.new(Utils::AnsiColors.ansi_colorize(data),
39
+ @colors = options[:colors] || AnsiColors.new
40
+ @template = ERB.new(@colors.ansi_colorize(data),
40
41
  nil, '-', '@buffer')
41
42
  @template.filename = filename if filename
42
43
  options.each_pair do |name, value|
43
44
  self[name] = value
44
45
  end
45
46
  end
46
-
47
+
47
48
  def []=(name, value)
48
49
  instance_variable_set("@#{name}".to_sym, value)
49
50
  return self
50
51
  end
51
-
52
+
52
53
  def result
53
54
  return @template.result(binding)
54
55
  end
@@ -78,8 +78,10 @@ define 'libcurl-dev' do
78
78
  if release =~ /release 4/
79
79
  # http://code.google.com/p/phusion-passenger/issues/detail?id=554
80
80
  yum_install "curl-devel zlib-devel e2fsprogs-devel krb5-devel libidn-devel"
81
- else
81
+ elsif release =~ /release 5/
82
82
  yum_install "curl-devel"
83
+ else
84
+ yum_install "libcurl-devel"
83
85
  end
84
86
  end
85
87
  end
@@ -1,5 +1,5 @@
1
1
  # Phusion Passenger - https://www.phusionpassenger.com/
2
- # Copyright (c) 2010-2013 Phusion
2
+ # Copyright (c) 2010-2014 Phusion
3
3
  #
4
4
  # "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
5
5
  #
@@ -20,12 +20,15 @@
20
20
  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
21
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
22
  # THE SOFTWARE.
23
+ PhusionPassenger.require_passenger_lib 'standalone/utils'
23
24
  PhusionPassenger.require_passenger_lib 'utils/file_system_watcher'
24
25
 
25
26
  module PhusionPassenger
26
27
  module Standalone
27
28
 
28
29
  class AppFinder
30
+ include Standalone::Utils
31
+
29
32
  attr_accessor :dirs
30
33
  attr_reader :apps
31
34
 
@@ -130,9 +133,9 @@ private
130
133
 
131
134
  def find_app_root
132
135
  if @dirs.empty?
133
- return File.expand_path(".")
136
+ return absolute_path(".")
134
137
  else
135
- return File.expand_path(@dirs[0])
138
+ return absolute_path(@dirs[0])
136
139
  end
137
140
  end
138
141
 
@@ -1,5 +1,5 @@
1
1
  # Phusion Passenger - https://www.phusionpassenger.com/
2
- # Copyright (c) 2010-2013 Phusion
2
+ # Copyright (c) 2010-2014 Phusion
3
3
  #
4
4
  # "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
5
5
  #
@@ -185,19 +185,19 @@ private
185
185
  end
186
186
  if @args.empty?
187
187
  if AppFinder.looks_like_app_directory?(".")
188
- @options[:pid_file] ||= File.expand_path("tmp/pids/#{pid_basename}")
189
- @options[:log_file] ||= File.expand_path("log/#{log_basename}")
188
+ @options[:pid_file] ||= absolute_path("tmp/pids/#{pid_basename}")
189
+ @options[:log_file] ||= absolute_path("log/#{log_basename}")
190
190
  if create_subdirs
191
191
  ensure_directory_exists(File.dirname(@options[:pid_file]))
192
192
  ensure_directory_exists(File.dirname(@options[:log_file]))
193
193
  end
194
194
  else
195
- @options[:pid_file] ||= File.expand_path(pid_basename)
196
- @options[:log_file] ||= File.expand_path(log_basename)
195
+ @options[:pid_file] ||= absolute_path(pid_basename)
196
+ @options[:log_file] ||= absolute_path(log_basename)
197
197
  end
198
198
  else
199
- @options[:pid_file] ||= File.expand_path(File.join(@args[0], pid_basename))
200
- @options[:log_file] ||= File.expand_path(File.join(@args[0], log_basename))
199
+ @options[:pid_file] ||= absolute_path(File.join(@args[0], pid_basename))
200
+ @options[:log_file] ||= absolute_path(File.join(@args[0], log_basename))
201
201
  end
202
202
  end
203
203
 
@@ -146,11 +146,11 @@ private
146
146
  end
147
147
  opts.on("--ssl-certificate PATH", String,
148
148
  wrap_desc("Specify the SSL certificate path")) do |val|
149
- @options[:ssl_certificate] = File.expand_path(val)
149
+ @options[:ssl_certificate] = absolute_path(val)
150
150
  end
151
151
  opts.on("--ssl-certificate-key PATH", String,
152
152
  wrap_desc("Specify the SSL key path")) do |val|
153
- @options[:ssl_certificate_key] = File.expand_path(val)
153
+ @options[:ssl_certificate_key] = absolute_path(val)
154
154
  end
155
155
  opts.on("--ssl-port PORT", Integer,
156
156
  wrap_desc("Listen for SSL on this port, while listening for HTTP on the normal port")) do |val|
@@ -203,11 +203,11 @@ private
203
203
  end
204
204
  opts.on("--static-files-dir PATH", String,
205
205
  wrap_desc("Specify the static files dir")) do |val|
206
- @options[:static_files_dir] = File.expand_path(val)
206
+ @options[:static_files_dir] = absolute_path(val)
207
207
  end
208
208
  opts.on("--restart-dir PATH", String,
209
209
  wrap_desc("Specify the restart dir")) do |val|
210
- @options[:restart_dir] = File.expand_path(val)
210
+ @options[:restart_dir] = absolute_path(val)
211
211
  end
212
212
  opts.on("--friendly-error-pages",
213
213
  wrap_desc("Turn on friendly error pages")) do
@@ -292,11 +292,11 @@ private
292
292
  opts.on("--nginx-tarball FILENAME", String,
293
293
  wrap_desc("If Nginx needs to be installed, then the given tarball will " +
294
294
  "be used instead of downloading from the Internet")) do |value|
295
- @options[:nginx_tarball] = File.expand_path(value)
295
+ @options[:nginx_tarball] = absolute_path(value)
296
296
  end
297
297
  opts.on("--nginx-config-template FILENAME", String,
298
298
  wrap_desc("The template to use for generating the Nginx config file")) do |value|
299
- @options[:nginx_config_template] = File.expand_path(value)
299
+ @options[:nginx_config_template] = absolute_path(value)
300
300
  end
301
301
  opts.on("--binaries-url-root URL", String,
302
302
  wrap_desc("If Nginx needs to be installed, then the specified URL will be " +
@@ -309,7 +309,7 @@ private
309
309
  end
310
310
  opts.on("--runtime-dir DIRECTORY", String,
311
311
  wrap_desc("Directory to use for Phusion Passenger Standalone runtime files")) do |value|
312
- @options[:runtime_dir] = File.expand_path(value)
312
+ @options[:runtime_dir] = absolute_path(value)
313
313
  end
314
314
  opts.on("--runtime-check-only",
315
315
  wrap_desc("Quit after checking whether the Phusion Passenger Standalone runtime files are installed")) do
@@ -737,7 +737,7 @@ private
737
737
 
738
738
  def nginx_listen_address(options = @options, for_ping_port = false)
739
739
  if options[:socket_file]
740
- return "unix:" + File.expand_path(options[:socket_file])
740
+ return "unix:" + absolute_path(options[:socket_file])
741
741
  else
742
742
  if for_ping_port
743
743
  port = options[:ping_port]
@@ -750,7 +750,7 @@ private
750
750
 
751
751
  def nginx_listen_address_with_ssl_port(options = @options)
752
752
  if options[:socket_file]
753
- return "unix:" + File.expand_path(options[:socket_file])
753
+ return "unix:" + absolute_path(options[:socket_file])
754
754
  else
755
755
  return compose_ip_and_port(options[:address], options[:ssl_port])
756
756
  end
@@ -1,5 +1,5 @@
1
1
  # Phusion Passenger - https://www.phusionpassenger.com/
2
- # Copyright (c) 2010 Phusion
2
+ # Copyright (c) 2010-2014 Phusion
3
3
  #
4
4
  # "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
5
5
  #
@@ -31,7 +31,7 @@ private
31
31
  PhusionPassenger.require_passenger_lib 'platform_info/binary_compatibility'
32
32
  end
33
33
  end
34
-
34
+
35
35
  def runtime_version_string(nginx_version)
36
36
  if PhusionPassenger.originally_packaged? || nginx_version != PhusionPassenger::PREFERRED_NGINX_VERSION
37
37
  require_platform_info_binary_compatibility
@@ -40,6 +40,18 @@ private
40
40
  return VERSION_STRING
41
41
  end
42
42
  end
43
+
44
+ # Dir.pwd resolves symlinks. So in turn, File.expand_path/File.absolute_path
45
+ # do that too. We work around that by shelling out to the `pwd` tool.
46
+ if File.respond_to?(:absolute_path)
47
+ def absolute_path(path)
48
+ return File.absolute_path(path, `pwd`.strip)
49
+ end
50
+ else
51
+ def absolute_path(path)
52
+ return File.expand_path(path, `pwd`.strip)
53
+ end
54
+ end
43
55
  end
44
56
 
45
57
  end
@@ -36,9 +36,13 @@ module AnsiColors
36
36
  BLACK_BG = "\e[40m".freeze
37
37
  BLUE_BG = "\e[44m".freeze
38
38
  DEFAULT_TERMINAL_COLOR = "#{RESET}#{WHITE}#{BLACK_BG}".freeze
39
-
39
+
40
40
  extend self # Make methods available as class methods.
41
-
41
+
42
+ def self.new(type = :auto)
43
+ return AnsiColorsPrinter.new(type)
44
+ end
45
+
42
46
  def self.included(klass)
43
47
  # When included into another class, make sure that Utils
44
48
  # methods are made private.
@@ -46,7 +50,7 @@ module AnsiColors
46
50
  klass.send(:private, method_name)
47
51
  end
48
52
  end
49
-
53
+
50
54
  def ansi_colorize(text)
51
55
  text = text.gsub(%r{<b>(.*?)</b>}m, "#{BOLD}\\1#{DEFAULT_TERMINAL_COLOR}")
52
56
  text.gsub!(%r{<dgray>(.*?)</dgray>}m, "#{BOLD}#{DGRAY}\\1#{DEFAULT_TERMINAL_COLOR}")
@@ -70,5 +74,80 @@ module AnsiColors
70
74
  end
71
75
  end
72
76
 
77
+ class AnsiColorsPrinter
78
+ def initialize(enabled = :auto)
79
+ @enabled = enabled
80
+ end
81
+
82
+ def reset
83
+ return maybe_colorize(AnsiColors::RESET)
84
+ end
85
+
86
+ def bold
87
+ return maybe_colorize(AnsiColors::BOLD)
88
+ end
89
+
90
+ def dgray
91
+ return maybe_colorize(AnsiColors::DGRAY)
92
+ end
93
+
94
+ def red
95
+ return maybe_colorize(AnsiColors::RED)
96
+ end
97
+
98
+ def orange
99
+ return maybe_colorize(AnsiColors::ORANGE)
100
+ end
101
+
102
+ def green
103
+ return maybe_colorize(AnsiColors::GREEN)
104
+ end
105
+
106
+ def yellow
107
+ return maybe_colorize(AnsiColors::YELLOW)
108
+ end
109
+
110
+ def white
111
+ return maybe_colorize(AnsiColors::WHITE)
112
+ end
113
+
114
+ def black_bg
115
+ return maybe_colorize(AnsiColors::BLACK_BG)
116
+ end
117
+
118
+ def blue_bg
119
+ return maybe_colorize(AnsiColors::BLUE_BG)
120
+ end
121
+
122
+ def default_terminal_color
123
+ return maybe_colorize(AnsiColors::DEFAULT_TERMINAL_COLOR)
124
+ end
125
+
126
+ def ansi_colorize(text)
127
+ if should_output_color?
128
+ return AnsiColors.ansi_colorize(text)
129
+ else
130
+ return AnsiColors.strip_color_tags(text)
131
+ end
132
+ end
133
+
134
+ private
135
+ def maybe_colorize(ansi_color)
136
+ if should_output_color?
137
+ return ansi_color
138
+ else
139
+ return ""
140
+ end
141
+ end
142
+
143
+ def should_output_color?
144
+ if @enabled == :auto
145
+ return STDOUT.tty?
146
+ else
147
+ return @enabled
148
+ end
149
+ end
150
+ end
151
+
73
152
  end # module Utils
74
153
  end # module PhusionPassenger
@@ -117,7 +117,7 @@ describe "Passenger Standalone" do
117
117
  end
118
118
 
119
119
  describe "start command" do
120
- SUPPORT_BINARIES_DOWNLOAD_MESSAGE = " --> Downloading #{PROGRAM_NAME} support binaries for your platform"
120
+ SUPPORT_BINARIES_DOWNLOAD_MESSAGE = "--> Downloading #{PROGRAM_NAME} support binaries for your platform"
121
121
  NGINX_BINARY_DOWNLOAD_MESSAGE = "Downloading web helper for your platform"
122
122
  NGINX_SOURCE_DOWNLOAD_MESSAGE = "Downloading web helper source code..."
123
123
  COMPILING_MESSAGE = "Installing #{PROGRAM_NAME} Standalone..."
@@ -224,7 +224,7 @@ describe "Passenger Standalone" do
224
224
  command = "passenger start " +
225
225
  "--runtime-dir '#{@runtime_dir}' " +
226
226
  "--binaries-url-root '#{@base_url}'"
227
-
227
+
228
228
  @output = `#{command} --runtime-check-only --no-compile-runtime 2>&1`
229
229
  $?.exitstatus.should_not == 0
230
230
  @output.should include(SUPPORT_BINARIES_DOWNLOAD_MESSAGE)
@@ -237,7 +237,7 @@ describe "Passenger Standalone" do
237
237
  @output.should include(NGINX_SOURCE_DOWNLOAD_MESSAGE)
238
238
  @output.should include(COMPILING_MESSAGE)
239
239
  File.exist?("#{PhusionPassenger.source_root}/buildout").should be_false
240
-
240
+
241
241
  test_serving_application("#{command} --no-compile-runtime")
242
242
  File.exist?("#{PhusionPassenger.source_root}/buildout").should be_false
243
243
  ensure
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: passenger
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.50
4
+ version: 4.0.51
5
5
  platform: ruby
6
6
  authors:
7
7
  - Phusion - http://www.phusion.nl/
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-27 00:00:00.000000000 Z
11
+ date: 2014-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
metadata.gz.asc CHANGED
@@ -2,11 +2,11 @@
2
2
  Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
3
3
  Comment: GPGTools - http://gpgtools.org
4
4
 
5
- iQEcBAABAgAGBQJT/ac4AAoJECrHRaUKISqMKgsH/iM7xF2pyeeSQgOSS8oHsCWF
6
- pw4m0EzF8u0ERZAGHGGCUxsKkEJZsHSKsol9auG87I3NVUZ8WumbRa7WKRkS/XHd
7
- lDRFe+rReIxeaF13vRlDUSMwSaVjlMwxGQgSM0WF3gRtqH6rvSmiG7O+ZADvnLag
8
- 4cX5kNLcj3ecwMB1e6G/Q34XAsgSmXCDASeqpJBM+dHAzssbNU/Xv5Q7SFfPS0Kx
9
- HEU6sj6wU7TPDLjDZDi90ejdbp5/cGVl50UA5DbzYcgiqwm6F2rS4nPXc8cD1Zvv
10
- zE/0vmWMnYfnSkSyWnF3/yuJLhsUVgZKCUkDBQDPE0/SsEik16B69l2sfa+5oQ8=
11
- =M7FV
5
+ iQEcBAABAgAGBQJUIqZfAAoJECrHRaUKISqM5OYH/iVQY/mnbiA+zU/YHv0T52F4
6
+ zoEWHeWsZlKx6n/unBAbauVUTYK/DMUlDcNbfTVWMbH7y2ndoX+LQvWTUmHpvjsU
7
+ f9AOtMZTLGzSYwDaROjXBkEyNekoNBTAWI7jLhAvJgyfrQw5xK+5maRadEthd12R
8
+ eczljd7jsr/VzUZU/iwcrcxS4Ye/8UPm6OpnHNycKgsLEEJK2pB1LBnQjYW+cjdn
9
+ Ffyse6SKEmDfX/qbO9XD6GyHv1cxcdX1wsy0HxzeRtp7EuQJHCy1WkSgfrryd+f1
10
+ DmBMs6xnUf1wyRiZkqCACr86qSM4ajO1LQX4Ajzc79YiTjiUKwB014drhq3qm+8=
11
+ =TO+m
12
12
  -----END PGP SIGNATURE-----