passenger 2.2.4 → 2.2.5

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 (105) hide show
  1. data/NEWS +137 -0
  2. data/Rakefile +101 -19
  3. data/bin/passenger-install-nginx-module +10 -3
  4. data/bin/passenger-make-enterprisey +1 -1
  5. data/doc/Users guide Apache.html +227 -92
  6. data/doc/Users guide Apache.txt +169 -75
  7. data/doc/Users guide Nginx.html +1 -1
  8. data/doc/cxxapi/Bucket_8h-source.html +1 -1
  9. data/doc/cxxapi/Configuration_8h-source.html +373 -338
  10. data/doc/cxxapi/DirectoryMapper_8h-source.html +1 -1
  11. data/doc/cxxapi/Hooks_8h-source.html +1 -1
  12. data/doc/cxxapi/annotated.html +1 -1
  13. data/doc/cxxapi/classHooks-members.html +1 -1
  14. data/doc/cxxapi/classHooks.html +2 -2
  15. data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +1 -1
  16. data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +1 -1
  17. data/doc/cxxapi/classes.html +1 -1
  18. data/doc/cxxapi/definitions_8h-source.html +1 -1
  19. data/doc/cxxapi/files.html +1 -1
  20. data/doc/cxxapi/functions.html +1 -1
  21. data/doc/cxxapi/functions_func.html +1 -1
  22. data/doc/cxxapi/graph_legend.html +1 -1
  23. data/doc/cxxapi/group__Configuration.html +1 -1
  24. data/doc/cxxapi/group__Core.html +1 -1
  25. data/doc/cxxapi/group__Hooks.html +1 -1
  26. data/doc/cxxapi/group__Support.html +1 -1
  27. data/doc/cxxapi/main.html +1 -1
  28. data/doc/cxxapi/modules.html +1 -1
  29. data/doc/rdoc/classes/ConditionVariable.html +59 -59
  30. data/doc/rdoc/classes/Exception.html +11 -11
  31. data/doc/rdoc/classes/GC.html +4 -4
  32. data/doc/rdoc/classes/IO.html +14 -14
  33. data/doc/rdoc/classes/PhusionPassenger.html +1 -1
  34. data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +8 -8
  35. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +136 -136
  36. data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +254 -254
  37. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +61 -61
  38. data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +4 -4
  39. data/doc/rdoc/classes/PhusionPassenger/Application.html +14 -14
  40. data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +12 -12
  41. data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +4 -4
  42. data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +12 -12
  43. data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +5 -5
  44. data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +139 -139
  45. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +61 -56
  46. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +3 -3
  47. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +7 -7
  48. data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +15 -15
  49. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +119 -119
  50. data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +4 -4
  51. data/doc/rdoc/classes/PhusionPassenger/Utils.html +310 -312
  52. data/doc/rdoc/classes/PhusionPassenger/Utils/PseudoIO.html +169 -0
  53. data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +4 -4
  54. data/doc/rdoc/classes/PlatformInfo.html +165 -164
  55. data/doc/rdoc/classes/Signal.html +23 -23
  56. data/doc/rdoc/created.rid +1 -1
  57. data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +1 -1
  58. data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +26 -28
  59. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +26 -28
  60. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +1 -1
  61. data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +1 -1
  62. data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +26 -28
  63. data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +1 -1
  64. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +1 -1
  65. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +26 -28
  66. data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +1 -2
  67. data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +1 -1
  68. data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +26 -28
  69. data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +26 -28
  70. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +34 -36
  71. data/doc/rdoc/fr_class_index.html +1 -0
  72. data/doc/rdoc/fr_method_index.html +72 -68
  73. data/ext/apache2/Configuration.cpp +69 -15
  74. data/ext/apache2/Configuration.h +37 -2
  75. data/ext/apache2/Hooks.cpp +167 -59
  76. data/ext/common/ApplicationPoolServerExecutable.cpp +1 -1
  77. data/ext/common/MessageChannel.h +4 -4
  78. data/ext/common/StandardApplicationPool.h +1 -1
  79. data/ext/common/Timer.h +2 -0
  80. data/ext/common/Version.h +1 -1
  81. data/ext/nginx/Configuration.c +3 -3
  82. data/ext/nginx/ContentHandler.c +16 -4
  83. data/ext/nginx/HelperServer.cpp +1 -1
  84. data/ext/oxt/system_calls.cpp +6 -1
  85. data/ext/oxt/thread.hpp +17 -2
  86. data/ext/phusion_passenger/native_support.c +4 -4
  87. data/lib/phusion_passenger/abstract_request_handler.rb +3 -3
  88. data/lib/phusion_passenger/abstract_server.rb +1 -0
  89. data/lib/phusion_passenger/constants.rb +1 -1
  90. data/lib/phusion_passenger/message_channel.rb +1 -0
  91. data/lib/phusion_passenger/platform_info.rb +3 -2
  92. data/lib/phusion_passenger/rack/request_handler.rb +11 -7
  93. data/lib/phusion_passenger/railz/application_spawner.rb +7 -4
  94. data/lib/phusion_passenger/railz/request_handler.rb +1 -0
  95. data/lib/phusion_passenger/spawn_manager.rb +1 -0
  96. data/lib/phusion_passenger/utils.rb +38 -20
  97. data/test/integration_tests/apache2_tests.rb +162 -100
  98. data/test/integration_tests/mycook_spec.rb +63 -62
  99. data/test/integration_tests/nginx_tests.rb +12 -5
  100. data/test/ruby/utils_spec.rb +98 -14
  101. data/test/stub/apache2/httpd.conf.erb +2 -1
  102. data/test/stub/rails_apps/mycook/app/controllers/welcome_controller.rb +8 -0
  103. data/test/support/apache2_controller.rb +5 -1
  104. data/test/support/test_helper.rb +42 -13
  105. metadata +7 -137
@@ -266,7 +266,7 @@ public:
266
266
  */
267
267
  class Client {
268
268
  private:
269
- static const int CLIENT_THREAD_STACK_SIZE = 1024 * 128;
269
+ static const int CLIENT_THREAD_STACK_SIZE = 1024 * 64;
270
270
 
271
271
  /** The Server that this Client object belongs to. */
272
272
  Server &server;
@@ -328,7 +328,7 @@ public:
328
328
  struct msghdr msg;
329
329
  struct iovec vec;
330
330
  char dummy[1];
331
- #if defined(__APPLE__) || defined(__SOLARIS__)
331
+ #if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)
332
332
  struct {
333
333
  struct cmsghdr header;
334
334
  int fd;
@@ -356,7 +356,7 @@ public:
356
356
  control_header = CMSG_FIRSTHDR(&msg);
357
357
  control_header->cmsg_level = SOL_SOCKET;
358
358
  control_header->cmsg_type = SCM_RIGHTS;
359
- #if defined(__APPLE__) || defined(__SOLARIS__)
359
+ #if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)
360
360
  control_header->cmsg_len = sizeof(control_data);
361
361
  control_data.fd = fileDescriptor;
362
362
  #else
@@ -504,7 +504,7 @@ public:
504
504
  struct msghdr msg;
505
505
  struct iovec vec;
506
506
  char dummy[1];
507
- #if defined(__APPLE__) || defined(__SOLARIS__)
507
+ #if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)
508
508
  // File descriptor passing macros (CMSG_*) seem to be broken
509
509
  // on 64-bit MacOS X. This structure works around the problem.
510
510
  struct {
@@ -543,7 +543,7 @@ public:
543
543
  || control_header->cmsg_type != SCM_RIGHTS) {
544
544
  throw IOException("No valid file descriptor received.");
545
545
  }
546
- #if defined(__APPLE__) || defined(__SOLARIS__)
546
+ #if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)
547
547
  return control_data.fd;
548
548
  #else
549
549
  return *((int *) CMSG_DATA(control_header));
@@ -104,7 +104,7 @@ private:
104
104
  static const int DEFAULT_MAX_IDLE_TIME = 120;
105
105
  static const int DEFAULT_MAX_POOL_SIZE = 20;
106
106
  static const int DEFAULT_MAX_INSTANCES_PER_APP = 0;
107
- static const int CLEANER_THREAD_STACK_SIZE = 1024 * 128;
107
+ static const int CLEANER_THREAD_STACK_SIZE = 1024 * 64;
108
108
  static const unsigned int MAX_GET_ATTEMPTS = 10;
109
109
  static const unsigned int GET_TIMEOUT = 5000; // In milliseconds.
110
110
 
@@ -63,6 +63,8 @@ public:
63
63
  * restart the timer.
64
64
  */
65
65
  void start() {
66
+ // TODO: We really use should clock_gettime() and the monotonic
67
+ // clock whenever possible, instead of gettimeofday()...
66
68
  gettimeofday(&startTime, NULL);
67
69
  }
68
70
 
@@ -26,6 +26,6 @@
26
26
  #define _PASSENGER_VERSION_H_
27
27
 
28
28
  /* Don't forget to update lib/phusion_passenger/constants.rb too. */
29
- #define PASSENGER_VERSION "2.2.4"
29
+ #define PASSENGER_VERSION "2.2.5"
30
30
 
31
31
  #endif /* _PASSENGER_VERSION_H */
@@ -278,13 +278,13 @@ passenger_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
278
278
  prev->upstream.ignore_client_abort, 0);
279
279
 
280
280
  ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
281
- prev->upstream.connect_timeout, 60000);
281
+ prev->upstream.connect_timeout, 600000);
282
282
 
283
283
  ngx_conf_merge_msec_value(conf->upstream.send_timeout,
284
- prev->upstream.send_timeout, 60000);
284
+ prev->upstream.send_timeout, 600000);
285
285
 
286
286
  ngx_conf_merge_msec_value(conf->upstream.read_timeout,
287
- prev->upstream.read_timeout, 60000);
287
+ prev->upstream.read_timeout, 600000);
288
288
 
289
289
  ngx_conf_merge_size_value(conf->upstream.send_lowat,
290
290
  prev->upstream.send_lowat, 0);
@@ -288,14 +288,16 @@ create_request(ngx_http_request_t *r)
288
288
  /* +1 for trailing null */
289
289
  len = sizeof("CONTENT_LENGTH") + ngx_strlen(buf) + 1;
290
290
 
291
- /* DOCUMENT_ROOT, SCRIPT_NAME and base URI */
291
+ /* DOCUMENT_ROOT, SCRIPT_NAME, RAILS_RELATIVE_URL_ROOT and PATH_INFO. */
292
292
  len += sizeof("DOCUMENT_ROOT") + context->public_dir.len + 1;
293
293
  if (context->base_uri.len > 0) {
294
294
  len += sizeof("SCRIPT_NAME") + context->base_uri.len + 1;
295
295
  len += sizeof("RAILS_RELATIVE_URL_ROOT") +
296
296
  context->base_uri.len + 1;
297
+ len += sizeof("PATH_INFO") + r->uri.len - context->base_uri.len + 1;
297
298
  } else {
298
299
  len += sizeof("SCRIPT_NAME") + sizeof("");
300
+ len += sizeof("PATH_INFO") + r->uri.len + 1;
299
301
  }
300
302
 
301
303
  /* Various other HTTP headers. */
@@ -445,7 +447,7 @@ create_request(ngx_http_request_t *r)
445
447
  b->last = ngx_snprintf(b->last, 10, "%ui", content_length);
446
448
  *b->last++ = (u_char) 0;
447
449
 
448
- /* Build DOCUMENT_ROOT, SCRIPT_NAME and base URI. */
450
+ /* Build DOCUMENT_ROOT, SCRIPT_NAME, RAILS_RELATIVE_URL_ROOT and PATH_INFO. */
449
451
  b->last = ngx_copy(b->last, "DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT"));
450
452
  b->last = ngx_copy(b->last, context->public_dir.data,
451
453
  context->public_dir.len + 1);
@@ -459,9 +461,18 @@ create_request(ngx_http_request_t *r)
459
461
  sizeof("RAILS_RELATIVE_URL_ROOT"));
460
462
  b->last = ngx_copy(b->last, context->base_uri.data,
461
463
  context->base_uri.len + 1);
464
+
465
+ b->last = ngx_copy(b->last, "PATH_INFO", sizeof("PATH_INFO"));
466
+ b->last = ngx_copy(b->last, r->uri.data + context->base_uri.len,
467
+ r->uri.len - context->base_uri.len);
468
+ b->last = ngx_copy(b->last, "", 1);
462
469
  } else {
463
470
  b->last = ngx_copy(b->last, "SCRIPT_NAME", sizeof("SCRIPT_NAME"));
464
471
  b->last = ngx_copy(b->last, "", sizeof(""));
472
+
473
+ b->last = ngx_copy(b->last, "PATH_INFO", sizeof("PATH_INFO"));
474
+ b->last = ngx_copy(b->last, r->uri.data, r->uri.len);
475
+ b->last = ngx_copy(b->last, "", 1);
465
476
  }
466
477
 
467
478
  /* Various other HTTP headers. */
@@ -469,7 +480,8 @@ create_request(ngx_http_request_t *r)
469
480
  && r->headers_in.content_type->value.len > 0) {
470
481
  b->last = ngx_copy(b->last, "CONTENT_TYPE", sizeof("CONTENT_TYPE"));
471
482
  b->last = ngx_copy(b->last, r->headers_in.content_type->value.data,
472
- r->headers_in.content_type->value.len + 1);
483
+ r->headers_in.content_type->value.len);
484
+ b->last = ngx_copy(b->last, "", 1);
473
485
  }
474
486
 
475
487
  #if (NGX_HTTP_SSL)
@@ -1187,7 +1199,7 @@ passenger_content_handler(ngx_http_request_t *r)
1187
1199
  u->abort_request = abort_request;
1188
1200
  u->finalize_request = finalize_request;
1189
1201
 
1190
- u->buffering = 1;
1202
+ u->buffering = 0;
1191
1203
 
1192
1204
  u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
1193
1205
  if (u->pipe == NULL) {
@@ -139,7 +139,7 @@ struct ClientDisconnectedException { };
139
139
  class Client {
140
140
  private:
141
141
  /** The client thread stack size in bytes. */
142
- static const int CLIENT_THREAD_STACK_SIZE = 1024 * 128;
142
+ static const int CLIENT_THREAD_STACK_SIZE = 1024 * 64;
143
143
 
144
144
  /** The client number for this Client object, assigned by Server. */
145
145
  unsigned int number;
@@ -127,6 +127,8 @@ syscalls::bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
127
127
  int
128
128
  syscalls::connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) {
129
129
  int ret;
130
+ // FIXME: I don't think this is entirely correct.
131
+ // http://www.madore.org/~david/computers/connect-intr.html
130
132
  CHECK_INTERRUPTION(
131
133
  ret == -1,
132
134
  ret = ::connect(sockfd, serv_addr, addrlen);
@@ -264,9 +266,12 @@ syscalls::time(time_t *t) {
264
266
 
265
267
  int
266
268
  syscalls::usleep(useconds_t usec) {
269
+ // We use syscalls::nanosleep() here to reuse the code that sleeps
270
+ // for the remaining amount of time, if a signal was received but
271
+ // system call interruption is disabled.
267
272
  struct timespec spec;
268
273
  spec.tv_sec = usec / 1000000;
269
- spec.tv_nsec = usec % 1000000;
274
+ spec.tv_nsec = usec % 1000000 * 1000;
270
275
  return syscalls::nanosleep(&spec, NULL);
271
276
  }
272
277
 
@@ -2,7 +2,7 @@
2
2
  * OXT - OS eXtensions for boosT
3
3
  * Provides important functionality necessary for writing robust server software.
4
4
  *
5
- * Copyright (c) 2008 Phusion
5
+ * Copyright (c) 2008, 2009 Phusion
6
6
  *
7
7
  * Permission is hereby granted, free of charge, to any person obtaining a copy
8
8
  * of this software and associated documentation files (the "Software"), to deal
@@ -34,6 +34,7 @@
34
34
  #ifdef OXT_BACKTRACE_IS_ENABLED
35
35
  #include <sstream>
36
36
  #endif
37
+ #include <limits.h> // for PTHREAD_STACK_MIN
37
38
 
38
39
  namespace oxt {
39
40
 
@@ -107,6 +108,15 @@ private:
107
108
  }
108
109
 
109
110
  public:
111
+ /**
112
+ * The platform's minimum stack size, in bytes.
113
+ */
114
+ #if defined(PTHREAD_STACK_MIN)
115
+ static const unsigned int MIN_STACK_SIZE = PTHREAD_STACK_MIN;
116
+ #else
117
+ static const unsigned int MIN_STACK_SIZE = 1024 * 128;
118
+ #endif
119
+
110
120
  /**
111
121
  * Create a new thread.
112
122
  *
@@ -118,7 +128,9 @@ public:
118
128
  * a name will be automatically chosen.
119
129
  * @param stack_size The stack size, in bytes, that the thread should
120
130
  * have. If 0 is specified, the operating system's default stack
121
- * size is used.
131
+ * size is used. If non-zero is specified, and the size is smaller
132
+ * than the operating system's minimum stack size, then the operating
133
+ * system's minimum stack size will be used.
122
134
  * @pre func must be copyable.
123
135
  * @throws boost::thread_resource_error Something went wrong during
124
136
  * creation of the thread.
@@ -127,6 +139,9 @@ public:
127
139
  initialize_data(name);
128
140
 
129
141
  set_thread_main_function(boost::bind(thread_main, func, data));
142
+ if (stack_size < MIN_STACK_SIZE) {
143
+ stack_size = MIN_STACK_SIZE;
144
+ }
130
145
  start_thread(stack_size);
131
146
  }
132
147
 
@@ -65,7 +65,7 @@ send_fd(VALUE self, VALUE socket_fd, VALUE fd_to_send) {
65
65
  struct msghdr msg;
66
66
  struct iovec vec;
67
67
  char dummy[1];
68
- #if defined(__APPLE__) || defined(__SOLARIS__)
68
+ #if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)
69
69
  struct {
70
70
  struct cmsghdr header;
71
71
  int fd;
@@ -94,7 +94,7 @@ send_fd(VALUE self, VALUE socket_fd, VALUE fd_to_send) {
94
94
  control_header->cmsg_level = SOL_SOCKET;
95
95
  control_header->cmsg_type = SCM_RIGHTS;
96
96
  control_payload = NUM2INT(fd_to_send);
97
- #if defined(__APPLE__) || defined(__SOLARIS__)
97
+ #if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)
98
98
  control_header->cmsg_len = sizeof(control_data);
99
99
  control_data.fd = control_payload;
100
100
  #else
@@ -125,7 +125,7 @@ recv_fd(VALUE self, VALUE socket_fd) {
125
125
  struct msghdr msg;
126
126
  struct iovec vec;
127
127
  char dummy[1];
128
- #if defined(__APPLE__) || defined(__SOLARIS__)
128
+ #if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)
129
129
  // File descriptor passing macros (CMSG_*) seem to be broken
130
130
  // on 64-bit MacOS X. This structure works around the problem.
131
131
  struct {
@@ -164,7 +164,7 @@ recv_fd(VALUE self, VALUE socket_fd) {
164
164
  rb_sys_fail("No valid file descriptor received.");
165
165
  return Qnil;
166
166
  }
167
- #if defined(__APPLE__) || defined(__SOLARIS__)
167
+ #if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)
168
168
  return INT2NUM(control_data.fd);
169
169
  #else
170
170
  return INT2NUM(*((int *) CMSG_DATA(control_header)));
@@ -1,3 +1,4 @@
1
+ # encoding: binary
1
2
  # Phusion Passenger - http://www.modrails.com/
2
3
  # Copyright (c) 2008, 2009 Phusion
3
4
  #
@@ -404,9 +405,8 @@ private
404
405
  undef rewind if respond_to?(:rewind)
405
406
  end
406
407
 
407
- # Set encoding for Ruby 1.9 compatibility.
408
- client.set_encoding(Encoding::BINARY) if client.respond_to?(:set_encoding)
409
- client.binmode
408
+ # There's no need to set the encoding for Ruby 1.9 because this
409
+ # source file is tagged with 'encoding: binary'.
410
410
 
411
411
  return client
412
412
  else
@@ -1,3 +1,4 @@
1
+ # encoding: binary
1
2
  # Phusion Passenger - http://www.modrails.com/
2
3
  # Copyright (c) 2008, 2009 Phusion
3
4
  #
@@ -24,7 +24,7 @@
24
24
  module PhusionPassenger
25
25
  # Phusion Passenger version number.
26
26
  # Don't forget to edit ext/common/Version.h too.
27
- VERSION_STRING = '2.2.4'
27
+ VERSION_STRING = '2.2.5'
28
28
 
29
29
  DEFAULT_FRAMEWORK_SPAWNER_MAX_IDLE_TIME = 30 * 60
30
30
  DEFAULT_APP_SPAWNER_MAX_IDLE_TIME = 10 * 60
@@ -1,3 +1,4 @@
1
+ # encoding: binary
1
2
  # Phusion Passenger - http://www.modrails.com/
2
3
  # Copyright (c) 2008, 2009 Phusion
3
4
  #
@@ -336,7 +336,6 @@ public
336
336
  # for portability reasons. These flags should be specified as last
337
337
  # when invoking the compiler.
338
338
  def self.portability_cflags
339
- # _GLIBCPP__PTHREADS is for fixing Boost compilation on OpenBSD.
340
339
  flags = ["-D_REENTRANT -I/usr/local/include"]
341
340
  if RUBY_PLATFORM =~ /solaris/
342
341
  flags << '-D_XOPEN_SOURCE=500 -D_XPG4_2 -D__EXTENSIONS__ -D__SOLARIS__ -D_FILE_OFFSET_BITS=64'
@@ -347,7 +346,9 @@ public
347
346
  flags << '-DBOOST_HAS_STDINT_H -D_GLIBCPP__PTHREADS'
348
347
  elsif RUBY_PLATFORM =~ /aix/
349
348
  flags << '-DOXT_DISABLE_BACKTRACES'
350
- elsif RUBY_PLATFORM =~ /sparc-linux/
349
+ elsif RUBY_PLATFORM =~ /(sparc-linux|arm-linux)/
350
+ # http://code.google.com/p/phusion-passenger/issues/detail?id=200
351
+ # http://groups.google.com/group/phusion-passenger/t/6b904a962ee28e5c
351
352
  flags << '-DBOOST_SP_USE_PTHREADS'
352
353
  end
353
354
  return flags.compact.join(" ").strip
@@ -1,3 +1,4 @@
1
+ # encoding: binary
1
2
  # Phusion Passenger - http://www.modrails.com/
2
3
  # Copyright (c) 2008, 2009 Phusion
3
4
  #
@@ -42,12 +43,10 @@ class RequestHandler < AbstractRequestHandler
42
43
  RACK_RUN_ONCE = "rack.run_once" # :nodoc:
43
44
  RACK_URL_SCHEME = "rack.url_scheme" # :nodoc:
44
45
  SCRIPT_NAME = "SCRIPT_NAME" # :nodoc:
45
- PATH_INFO = "PATH_INFO" # :nodoc:
46
- REQUEST_URI = "REQUEST_URI" # :nodoc:
47
- QUESTION_MARK = "?" # :nodoc:
48
- QUERY_STRING = "QUERY_STRING" # :nodoc:
49
46
  CONTENT_LENGTH = "CONTENT_LENGTH" # :nodoc:
47
+ CONTENT_TYPE = "CONTENT_TYPE" # :nodoc:
50
48
  HTTP_CONTENT_LENGTH = "HTTP_CONTENT_LENGTH" # :nodoc:
49
+ HTTP_CONTENT_TYPE = "HTTP_CONTENT_TYPE" # :nodoc:
51
50
  HTTPS = "HTTPS" # :nodoc:
52
51
  HTTPS_DOWNCASE = "https" # :nodoc:
53
52
  HTTP = "http" # :nodoc:
@@ -73,15 +72,20 @@ protected
73
72
  env[RACK_MULTITHREAD] = false
74
73
  env[RACK_MULTIPROCESS] = true
75
74
  env[RACK_RUN_ONCE] = false
76
- env[QUERY_STRING] ||= ""
77
- env[PATH_INFO] ||= env[REQUEST_URI].split(QUESTION_MARK, 2).first
78
- env[PATH_INFO].sub!(/^#{Regexp.escape(env[SCRIPT_NAME])}/, "")
75
+
79
76
  if env[HTTP_CONTENT_LENGTH] && env[CONTENT_LENGTH]
80
77
  env.delete(HTTP_CONTENT_LENGTH)
81
78
  elsif env[HTTP_CONTENT_LENGTH] && !env[CONTENT_LENGTH]
82
79
  env[CONTENT_LENGTH] = env[HTTP_CONTENT_LENGTH]
83
80
  env.delete(HTTP_CONTENT_LENGTH)
84
81
  end
82
+ if env[HTTP_CONTENT_TYPE] && env[CONTENT_TYPE]
83
+ env.delete(HTTP_CONTENT_TYPE)
84
+ elsif env[HTTP_CONTENT_TYPE] && !env[CONTENT_TYPE]
85
+ env[CONTENT_TYPE] = env[HTTP_CONTENT_TYPE]
86
+ env.delete(HTTP_CONTENT_TYPE)
87
+ end
88
+
85
89
  if env[HTTPS] == YES || env[HTTPS] == ON || env[HTTPS] == ONE
86
90
  env[RACK_URL_SCHEME] = HTTPS_DOWNCASE
87
91
  else
@@ -300,7 +300,7 @@ private
300
300
  if File.exist?('config/preinitializer.rb')
301
301
  require 'config/preinitializer'
302
302
  end
303
- require 'config/environment'
303
+ require File.expand_path('config/environment')
304
304
  if ActionController::Base.page_cache_directory.blank?
305
305
  ActionController::Base.page_cache_directory = "#{RAILS_ROOT}/public"
306
306
  end
@@ -321,9 +321,11 @@ private
321
321
  # isn't copy-on-write friendly.
322
322
  # - Rails >= 2.2 already preloads application sources by default, so no need
323
323
  # to do that again.
324
- if GC.copy_on_write_friendly? && !::Rails::Initializer.respond_to?(:load_application_classes)
325
- Dir.glob('app/{models,controllers,helpers}/*.rb').each do |file|
326
- require_dependency canonicalize_path(file)
324
+ if GC.copy_on_write_friendly? && !::Rails::Initializer.method_defined?(:load_application_classes)
325
+ ['models','controllers','helpers'].each do |section|
326
+ Dir.glob("app/#{section}}/*.rb").each do |file|
327
+ require_dependency canonicalize_path(file)
328
+ end
327
329
  end
328
330
  end
329
331
  end
@@ -385,3 +387,4 @@ end
385
387
 
386
388
  end # module Railz
387
389
  end # module PhusionPassenger
390
+
@@ -1,3 +1,4 @@
1
+ # encoding: binary
1
2
  # Phusion Passenger - http://www.modrails.com/
2
3
  # Copyright (c) 2008, 2009 Phusion
3
4
  #
@@ -1,3 +1,4 @@
1
+ # encoding: binary
1
2
  # Phusion Passenger - http://www.modrails.com/
2
3
  # Copyright (c) 2008, 2009 Phusion
3
4
  #
@@ -1,3 +1,4 @@
1
+ # encoding: binary
1
2
  # Phusion Passenger - http://www.modrails.com/
2
3
  # Copyright (c) 2008, 2009 Phusion
3
4
  #
@@ -200,16 +201,37 @@ protected
200
201
  end
201
202
  end
202
203
 
204
+ class PseudoIO
205
+ def initialize(sink)
206
+ @sink = sink || File.open("/dev/null", "w")
207
+ @buffer = StringIO.new
208
+ end
209
+
210
+ def done!
211
+ result = @buffer.string
212
+ @buffer = nil
213
+ return result
214
+ end
215
+
216
+ def method_missing(*args, &block)
217
+ @buffer.send(*args, &block) if @buffer && args.first != :reopen
218
+ return @sink.send(*args, &block)
219
+ end
220
+
221
+ def respond_to?(symbol, include_private = false)
222
+ return @sink.respond_to?(symbol, include_private)
223
+ end
224
+ end
225
+
203
226
  # Run the given block. A message will be sent through +channel+ (a
204
227
  # MessageChannel object), telling the remote side whether the block
205
228
  # raised an exception, called exit(), or succeeded.
206
229
  #
207
- # Anything written to $stderr and STDERR during execution of the block
208
- # will be buffered. If <tt>write_stderr_contents_to</tt> is non-nil,
209
- # then the buffered stderr data will be written to this object. In this
210
- # case, <tt>write_stderr_contents_to</tt> must be an IO-like object.
211
- # If <tt>write_stderr_contents_to</tt> is nil, then the stder data will
212
- # be discarded.
230
+ # If _sink_ is non-nil, then every operation on $stderr/STDERR inside
231
+ # the block will be performed on _sink_ as well. If _sink_ is nil
232
+ # then all operations on $stderr/STDERR inside the block will be
233
+ # silently discarded, i.e. if one writes to $stderr/STDERR then nothing
234
+ # will be actually written to the console.
213
235
  #
214
236
  # Returns whether the block succeeded, i.e. whether it didn't raise an
215
237
  # exception.
@@ -217,30 +239,26 @@ protected
217
239
  # Exceptions are not propagated, except SystemExit and a few
218
240
  # non-StandardExeption classes such as SignalException. Of the
219
241
  # exceptions that are propagated, only SystemExit will be reported.
220
- def report_app_init_status(channel, write_stderr_contents_to = STDERR)
242
+ def report_app_init_status(channel, sink = STDERR)
221
243
  begin
222
244
  old_global_stderr = $stderr
223
245
  old_stderr = STDERR
224
246
  stderr_output = ""
225
- tempfile = Tempfile.new('passenger-stderr')
226
- tempfile.unlink
247
+
248
+ pseudo_stderr = PseudoIO.new(sink)
227
249
  Object.send(:remove_const, 'STDERR') rescue nil
228
- Object.const_set('STDERR', tempfile)
250
+ Object.const_set('STDERR', pseudo_stderr)
251
+ $stderr = pseudo_stderr
252
+
229
253
  begin
230
254
  yield
231
255
  ensure
232
256
  Object.send(:remove_const, 'STDERR') rescue nil
233
257
  Object.const_set('STDERR', old_stderr)
234
258
  $stderr = old_global_stderr
235
- tempfile.rewind
236
- stderr_output = tempfile.read
237
- tempfile.close rescue nil
238
-
239
- if write_stderr_contents_to
240
- write_stderr_contents_to.write(stderr_output)
241
- write_stderr_contents_to.flush
242
- end
259
+ stderr_output = pseudo_stderr.done!
243
260
  end
261
+
244
262
  channel.write('success')
245
263
  return true
246
264
  rescue StandardError, ScriptError, NoMemoryError => e
@@ -558,9 +576,9 @@ module Signal
558
576
  end
559
577
 
560
578
  # Ruby's implementation of UNIXSocket#recv_io and UNIXSocket#send_io
561
- # are broken on 64-bit FreeBSD 7 and x86_64/ppc64 OS X. So we override them
579
+ # are broken on 64-bit FreeBSD 7, OpenBSD and x86_64/ppc64 OS X. So we override them
562
580
  # with our own implementation.
563
- if RUBY_PLATFORM =~ /freebsd/ || (RUBY_PLATFORM =~ /darwin/ && RUBY_PLATFORM !~ /universal/)
581
+ if RUBY_PLATFORM =~ /freebsd/ || RUBY_PLATFORM =~ /openbsd/ || (RUBY_PLATFORM =~ /darwin/ && RUBY_PLATFORM !~ /universal/)
564
582
  require 'socket'
565
583
  UNIXSocket.class_eval do
566
584
  def recv_io