passenger 5.0.23 → 5.0.24

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +16 -1
  3. data/bin/passenger-install-apache2-module +1 -1
  4. data/build/basics.rb +1 -1
  5. data/build/cplusplus_support.rb +1 -1
  6. data/build/integration_tests.rb +1 -1
  7. data/build/packaging.rb +1 -1
  8. data/resources/templates/standalone/http.erb +1 -0
  9. data/src/agent/Core/ApiServer.h +91 -38
  10. data/src/agent/Core/ApplicationPool/Pool.h +2 -1
  11. data/src/agent/Core/ApplicationPool/Pool/GroupUtils.cpp +2 -1
  12. data/src/agent/Core/ApplicationPool/Pool/Miscellaneous.cpp +28 -1
  13. data/src/agent/Core/ApplicationPool/Process.h +3 -0
  14. data/src/agent/Core/Controller/CheckoutSession.cpp +2 -2
  15. data/src/agent/Core/Controller/ForwardResponse.cpp +1 -1
  16. data/src/agent/Core/Controller/Request.h +2 -2
  17. data/src/agent/Core/CoreMain.cpp +3 -2
  18. data/src/agent/Core/OptionParser.h +5 -0
  19. data/src/agent/Core/UnionStation/StopwatchLog.h +34 -60
  20. data/src/agent/UstRouter/ApiServer.h +27 -14
  21. data/src/apache2_module/Configuration.cpp +6 -0
  22. data/src/apache2_module/Configuration.hpp +4 -0
  23. data/src/apache2_module/Hooks.cpp +1 -0
  24. data/src/cxx_supportlib/Constants.h +3 -1
  25. data/src/cxx_supportlib/ServerKit/FdSinkChannel.h +1 -1
  26. data/src/cxx_supportlib/Utils.cpp +1 -1
  27. data/src/nginx_module/CacheLocationConfig.c +26 -0
  28. data/src/nginx_module/Configuration.c +5 -0
  29. data/src/nginx_module/Configuration.h +1 -0
  30. data/src/nginx_module/ConfigurationCommands.c +10 -0
  31. data/src/nginx_module/ConfigurationFields.h +2 -0
  32. data/src/nginx_module/CreateLocationConfig.c +4 -0
  33. data/src/nginx_module/MergeLocationConfig.c +6 -0
  34. data/src/nginx_module/ngx_http_passenger_module.c +1 -0
  35. data/src/ruby_supportlib/phusion_passenger.rb +3 -3
  36. data/src/ruby_supportlib/phusion_passenger/admin_tools/memory_stats.rb +11 -11
  37. data/src/ruby_supportlib/phusion_passenger/apache2/config_options.rb +3 -3
  38. data/src/ruby_supportlib/phusion_passenger/constants.rb +1 -0
  39. data/src/ruby_supportlib/phusion_passenger/native_support.rb +30 -10
  40. data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +6 -0
  41. data/src/ruby_supportlib/phusion_passenger/platform_info/apache.rb +7 -7
  42. data/src/ruby_supportlib/phusion_passenger/platform_info/binary_compatibility.rb +3 -3
  43. data/src/ruby_supportlib/phusion_passenger/platform_info/compiler.rb +8 -8
  44. data/src/ruby_supportlib/phusion_passenger/platform_info/cxx_portability.rb +7 -7
  45. data/src/ruby_supportlib/phusion_passenger/platform_info/depcheck.rb +4 -4
  46. data/src/ruby_supportlib/phusion_passenger/platform_info/linux.rb +1 -1
  47. data/src/ruby_supportlib/phusion_passenger/platform_info/openssl.rb +2 -2
  48. data/src/ruby_supportlib/phusion_passenger/platform_info/operating_system.rb +22 -9
  49. data/src/ruby_supportlib/phusion_passenger/platform_info/ruby.rb +1 -1
  50. data/src/ruby_supportlib/phusion_passenger/ruby_core_enhancements.rb +2 -2
  51. data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +14 -1
  52. data/src/ruby_supportlib/phusion_passenger/standalone/start_command.rb +1 -1
  53. data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +1 -0
  54. data/src/ruby_supportlib/phusion_passenger/utils/hosts_file_parser.rb +1 -1
  55. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9860ce906b0de7200f82e30d96333f500e57dd64
4
- data.tar.gz: 68ecdbe231a4e6484ec1336ab395858bcb54e19a
3
+ metadata.gz: 0af1aea8f91dd9fc4b54c4c25c3ae15e36aabc62
4
+ data.tar.gz: 9f6890815b77b348c99a81b5dd3c1c28b9226520
5
5
  SHA512:
6
- metadata.gz: 8ba93ff84710a7f93351551340173219326ce2b8672172980ccc9f29dea0e5fb8120533fc1abea5a3f71bca3895e19c2813e5872ad22aef6cf4dd4d719d542be
7
- data.tar.gz: a4293240d2581fa7d2f6b8abc2ebee0c7eedf338aff91b65a18e7d6ae2c924ef81fe1fa4fd3d15dc1ff70b09ee67513aff04daee0f706fd83d4370b5fb2cf632
6
+ metadata.gz: e59f5e66d3f9bf483ab9e4e32570b76ff9a63ac0c38e0c3bc2b8a161068012663d7ecc6b0ac0335017ea4da01bdf2b4b2db2bbe65fe462d889f508bccca31d40
7
+ data.tar.gz: d05d4492c67ba8d0135b4ae5ab6e81cdaa907ffe0457d996b604be838b8322007935fe42091ace80eec96eeecd25490d997962673beb954e051a4a6f3b87c018
data/CHANGELOG CHANGED
@@ -1,3 +1,18 @@
1
+ Release 5.0.24
2
+ --------------
3
+
4
+ * Fixes a crash when the new `force_max_concurrent_requests_per_process` option (5.0.22) was used for non-Node.js apps (e.g. Ruby). Closes GH-1720.
5
+ * Fixes Solaris compilation. This was a regression due to the patch for GH-1643 in 5.0.22. Closes GH-1694, GH-1701.
6
+ * Logs for [Union Station](https://www.unionstationapp.com) provide more information about request queueing. Closes GH-1633.
7
+ * Also log HTTP headers to Union Station for HTTP 4xx responses (extends the header logging for HTTP 5xx that was added in 5.0.22)
8
+ * Fixes cases where compilation failure of (optional) native utils was not reported.
9
+ * On Ruby, no longer traps SIGEXIT. This fixes erroneously setting `$ERROR_INFO` in `at_exit` callbacks. Closes GH-1730.
10
+ * Fixes a wrong loop exit condition that could cause a deadlock with 100% CPU usage by Passenger core. Closes GH-1709, GH-1732.
11
+ * Adds `socket_backlog` option to configure the Passenger Core socket backlog. For use with e.g. "Resource temporarily unavailable while connecting to upstream" errors. Closes GH-1726.
12
+ * [Nginx] The preferred Nginx version is now 1.8.1 (previously 1.8.0).
13
+ * [Standalone] Fixes the default value of the `load_shell_envvars` option. It's supposed to be disabled by default, but due to a typo it was enabled by default.
14
+
15
+
1
16
  Release 5.0.23
2
17
  --------------
3
18
 
@@ -12,7 +27,7 @@ Release 5.0.23
12
27
  Release 5.0.22
13
28
  --------------
14
29
 
15
- * Fixes a header collision vulnerability (CVE-2015-7519, medium severity). Please see our blog for detailed vulnerability description and advisory. Thanks to the SUSE security team for reporting this issue.
30
+ * Fixes a header collision vulnerability (CVE-2015-7519, medium severity). Note that this fix involves filtering request headers containing underscores. Please see our blog for detailed vulnerability description and advisory. Thanks to the SUSE security team for reporting this issue.
16
31
  * [Apache] Fixes compatibility with Apache 2.4.17's mod_autoindex. Fix contributed by Eric Covener. Closes GH-1642.
17
32
  * [Standalone] Passenger Standalone now [accepts configuration options from environment variables](https://www.phusionpassenger.com/library/config/standalone/intro.html). This makes using Passenger Standalone significantly easier on Heroku or on systems that follow the 12-factor principle. Closes GH-1661.
18
33
  * [Standalone] The Nginx configuration template has been cleaned up. It is now significantly easier to edit the Nginx configuration template without breaking compatibility with future versions.
@@ -154,7 +154,7 @@ private
154
154
 
155
155
  def check_selinux_and_suggest_rpm
156
156
  return if !PhusionPassenger.originally_packaged? ||
157
- PlatformInfo.os_name != "linux" ||
157
+ PlatformInfo.os_name_simple != "linux" ||
158
158
  !(PlatformInfo.linux_distro_tags.include?(:rhel) ||
159
159
  PlatformInfo.linux_distro_tags.include?(:centos))
160
160
  !PlatformInfo.find_command('sestatus')
@@ -182,7 +182,7 @@ AGENT_LDFLAGS << " -lselinux" if USE_SELINUX
182
182
  # Extra linker flags for backtrace_symbols() to generate useful output (see agent/Base.cpp).
183
183
  AGENT_LDFLAGS << " #{PlatformInfo.export_dynamic_flags}"
184
184
  # Enable dead symbol elimination on OS X.
185
- AGENT_LDFLAGS << " -Wl,-dead_strip" if PlatformInfo.os_name == "macosx"
185
+ AGENT_LDFLAGS << " -Wl,-dead_strip" if PlatformInfo.os_name_simple == "macosx"
186
186
  AGENT_LDFLAGS.strip!
187
187
 
188
188
  # Extra compiler flags that should always be passed to the C/C++ compiler.
@@ -131,7 +131,7 @@ def create_static_library(target, objects)
131
131
  end
132
132
 
133
133
  def create_shared_library(target, objects, options_or_flags = nil)
134
- if PlatformInfo.os_name == "macosx"
134
+ if PlatformInfo.os_name_simple == "macosx"
135
135
  shlib_flag = "-flat_namespace -bundle -undefined dynamic_lookup"
136
136
  else
137
137
  shlib_flag = "-shared"
@@ -89,7 +89,7 @@ task 'test:integration:native_packaging' do
89
89
  require 'shellwords'
90
90
  command << " -e #{Shellwords.escape(grep)}"
91
91
  end
92
- case PlatformInfo.os_name
92
+ case PlatformInfo.os_name_simple
93
93
  when "linux"
94
94
  if PlatformInfo.linux_distro_tags.include?(:debian)
95
95
  rubylibdir = RbConfig::CONFIG["vendordir"]
@@ -283,7 +283,7 @@ task 'package:tarball' => Packaging::PREGENERATED_FILES do
283
283
  if ENV['OFFICIAL_RELEASE']
284
284
  File.open("#{PKG_DIR}/#{basename}/resources/release.txt", "w").close
285
285
  end
286
- if PlatformInfo.os_name == "macosx"
286
+ if PlatformInfo.os_name_simple == "macosx"
287
287
  sh "cd #{PKG_DIR}/#{basename} && find . -print0 | xargs -0 touch -t '201310270000'"
288
288
  else
289
289
  sh "cd #{PKG_DIR}/#{basename} && find . -print0 | xargs -0 touch -d '2013-10-27 00:00:00 UTC'"
@@ -23,6 +23,7 @@ passenger_user_switching off;
23
23
  passenger_analytics_log_user <%= current_user %>;
24
24
  <% end %>
25
25
 
26
+ <%= nginx_http_option(:socket_backlog) %>
26
27
  <%= nginx_http_option(:python) %>
27
28
  <%= nginx_http_option(:nodejs) %>
28
29
  <%= nginx_http_option(:log_level) %>
@@ -61,6 +61,8 @@ public:
61
61
  string body;
62
62
  Json::Value jsonBody;
63
63
  Authorization authorization;
64
+ unsigned int controllerStatesGathered;
65
+ vector<Json::Value> controllerStates;
64
66
 
65
67
  DEFINE_SERVER_KIT_BASE_HTTP_REQUEST_FOOTER(Passenger::Core::ApiServer::Request);
66
68
  };
@@ -172,30 +174,56 @@ private:
172
174
  }
173
175
  }
174
176
 
175
- static void inspectControllerState(Controller *controller, Json::Value *json) {
176
- *json = controller->inspectStateAsJson();
177
+ void gatherControllerState(Client *client, Request *req,
178
+ Controller *controller, unsigned int i)
179
+ {
180
+ Json::Value state = controller->inspectStateAsJson();
181
+ getContext()->libev->runLater(boost::bind(&ApiServer::controllerStateGathered,
182
+ this, client, req, i, state));
177
183
  }
178
184
 
179
- void processServerStatus(Client *client, Request *req) {
180
- if (authorizeStateInspectionOperation(this, client, req)) {
185
+ void controllerStateGathered(Client *client, Request *req,
186
+ unsigned int i, Json::Value state)
187
+ {
188
+ if (req->ended()) {
189
+ unrefRequest(req, __FILE__, __LINE__);
190
+ return;
191
+ }
192
+
193
+ req->controllerStatesGathered++;
194
+ req->controllerStates[i] = state;
195
+
196
+ if (req->controllerStatesGathered == controllers.size()) {
181
197
  HeaderTable headers;
182
198
  headers.insert(req->pool, "Content-Type", "application/json");
183
199
 
184
- Json::Value doc;
185
- doc["threads"] = (Json::UInt) controllers.size();
200
+ Json::Value response;
201
+ response["threads"] = (Json::UInt) controllers.size();
202
+
186
203
  for (unsigned int i = 0; i < controllers.size(); i++) {
187
- Json::Value json;
188
204
  string key = "thread" + toString(i + 1);
189
-
190
- controllers[i]->getContext()->libev->runSync(boost::bind(
191
- inspectControllerState, controllers[i], &json));
192
- doc[key] = json;
205
+ response[key] = req->controllerStates[i];
193
206
  }
194
207
 
195
208
  writeSimpleResponse(client, 200, &headers,
196
- psg_pstrdup(req->pool, doc.toStyledString()));
209
+ psg_pstrdup(req->pool, response.toStyledString()));
197
210
  if (!req->ended()) {
198
- endRequest(&client, &req);
211
+ Request *req2 = req;
212
+ endRequest(&client, &req2);
213
+ }
214
+ }
215
+
216
+ unrefRequest(req, __FILE__, __LINE__);
217
+ }
218
+
219
+ void processServerStatus(Client *client, Request *req) {
220
+ if (authorizeStateInspectionOperation(this, client, req)) {
221
+ req->controllerStates.resize(controllers.size());
222
+ for (unsigned int i = 0; i < controllers.size(); i++) {
223
+ refRequest(req, __FILE__, __LINE__);
224
+ controllers[i]->getContext()->libev->runLater(boost::bind(
225
+ &ApiServer::gatherControllerState, this,
226
+ client, req, controllers[i], i));
199
227
  }
200
228
  } else {
201
229
  apiServerRespondWith401(this, client, req);
@@ -407,37 +435,16 @@ private:
407
435
  }
408
436
  }
409
437
 
410
- static void getControllerConfig(Controller *controller, Json::Value *json) {
411
- *json = controller->getConfigAsJson();
412
- }
413
-
414
438
  void processConfig(Client *client, Request *req) {
415
439
  if (req->method == HTTP_GET) {
416
440
  if (!authorizeStateInspectionOperation(this, client, req)) {
417
441
  apiServerRespondWith401(this, client, req);
418
442
  }
419
443
 
420
- HeaderTable headers;
421
- string logFile = getLogFile();
422
- string fileDescriptorLogFile = getFileDescriptorLogFile();
423
-
424
- headers.insert(req->pool, "Content-Type", "application/json");
425
- Json::Value doc;
426
- controllers[0]->getContext()->libev->runSync(boost::bind(
427
- getControllerConfig, controllers[0], &doc));
428
- doc["log_level"] = getLogLevel();
429
- if (!logFile.empty()) {
430
- doc["log_file"] = logFile;
431
- }
432
- if (!fileDescriptorLogFile.empty()) {
433
- doc["file_descriptor_log_file"] = fileDescriptorLogFile;
434
- }
435
-
436
- writeSimpleResponse(client, 200, &headers,
437
- psg_pstrdup(req->pool, doc.toStyledString()));
438
- if (!req->ended()) {
439
- endRequest(&client, &req);
440
- }
444
+ refRequest(req, __FILE__, __LINE__);
445
+ controllers[0]->getContext()->libev->runLater(boost::bind(
446
+ &ApiServer::processConfig_getControllerConfig, this,
447
+ client, req, controllers[0]));
441
448
  } else if (req->method == HTTP_PUT) {
442
449
  if (!authorizeAdminOperation(this, client, req)) {
443
450
  apiServerRespondWith401(this, client, req);
@@ -450,6 +457,46 @@ private:
450
457
  }
451
458
  }
452
459
 
460
+ void processConfig_getControllerConfig(Client *client, Request *req,
461
+ Controller *controller)
462
+ {
463
+ Json::Value config = controller->getConfigAsJson();
464
+ getContext()->libev->runLater(boost::bind(
465
+ &ApiServer::processConfig_controllerConfigGathered, this,
466
+ client, req, controller, config));
467
+ }
468
+
469
+ void processConfig_controllerConfigGathered(Client *client, Request *req,
470
+ Controller *controller, Json::Value config)
471
+ {
472
+ if (req->ended()) {
473
+ unrefRequest(req, __FILE__, __LINE__);
474
+ return;
475
+ }
476
+
477
+ HeaderTable headers;
478
+ string logFile = getLogFile();
479
+ string fileDescriptorLogFile = getFileDescriptorLogFile();
480
+
481
+ headers.insert(req->pool, "Content-Type", "application/json");
482
+ config["log_level"] = getLogLevel();
483
+ if (!logFile.empty()) {
484
+ config["log_file"] = logFile;
485
+ }
486
+ if (!fileDescriptorLogFile.empty()) {
487
+ config["file_descriptor_log_file"] = fileDescriptorLogFile;
488
+ }
489
+
490
+ writeSimpleResponse(client, 200, &headers,
491
+ psg_pstrdup(req->pool, config.toStyledString()));
492
+ if (!req->ended()) {
493
+ Request *req2 = req;
494
+ endRequest(&client, &req2);
495
+ }
496
+
497
+ unrefRequest(req, __FILE__, __LINE__);
498
+ }
499
+
453
500
  static void configureController(Controller *controller, Json::Value json) {
454
501
  controller->configure(json);
455
502
  }
@@ -575,12 +622,18 @@ protected:
575
622
  return ServerKit::Channel::Result(buffer.size(), false);
576
623
  }
577
624
 
625
+ virtual void reinitializeRequest(Client *client, Request *req) {
626
+ ParentClass::reinitializeRequest(client, req);
627
+ req->controllerStatesGathered = 0;
628
+ }
629
+
578
630
  virtual void deinitializeRequest(Client *client, Request *req) {
579
631
  req->body.clear();
580
632
  if (!req->jsonBody.isNull()) {
581
633
  req->jsonBody = Json::Value();
582
634
  }
583
635
  req->authorization = Authorization();
636
+ req->controllerStates.clear();
584
637
  ParentClass::deinitializeRequest(client, req);
585
638
  }
586
639
 
@@ -58,6 +58,7 @@
58
58
  #include <Utils/VariantMap.h>
59
59
  #include <Utils/ProcessMetricsCollector.h>
60
60
  #include <Utils/SystemMetricsCollector.h>
61
+ #include <Core/UnionStation/StopwatchLog.h>
61
62
  #include <Core/ApplicationPool/Common.h>
62
63
  #include <Core/ApplicationPool/Context.h>
63
64
  #include <Core/ApplicationPool/Process.h>
@@ -448,7 +449,7 @@ public:
448
449
 
449
450
  /****** Miscellaneous ******/
450
451
 
451
- void asyncGet(const Options &options, const GetCallback &callback, bool lockNow = true);
452
+ void asyncGet(const Options &options, const GetCallback &callback, bool lockNow = true, UnionStation::StopwatchLog **stopwatchLog = NULL);
452
453
  SessionPtr get(const Options &options, Ticket *ticket);
453
454
  void setMax(unsigned int max);
454
455
  void setMaxIdleTime(unsigned long long value);
@@ -40,7 +40,8 @@ using namespace boost;
40
40
 
41
41
  /****************************
42
42
  *
43
- * Private methods
43
+ * Consider these to be private methods,
44
+ * they are only marked public for unit testing!
44
45
  *
45
46
  ****************************/
46
47
 
@@ -41,7 +41,7 @@ using namespace boost;
41
41
  // 'lockNow == false' may only be used during unit tests. Normally we
42
42
  // should never call the callback while holding the lock.
43
43
  void
44
- Pool::asyncGet(const Options &options, const GetCallback &callback, bool lockNow) {
44
+ Pool::asyncGet(const Options &options, const GetCallback &callback, bool lockNow, UnionStation::StopwatchLog **stopwatchLog) {
45
45
  DynamicScopedLock lock(syncher, lockNow);
46
46
 
47
47
  assert(lifeStatus == ALIVE || lifeStatus == PREPARED_FOR_SHUTDOWN);
@@ -50,6 +50,33 @@ Pool::asyncGet(const Options &options, const GetCallback &callback, bool lockNow
50
50
  boost::container::vector<Callback> actions;
51
51
 
52
52
  Group *existingGroup = findMatchingGroup(options);
53
+ if (stopwatchLog != NULL) {
54
+ // Log some essentials stats about what this request is facing in its upcoming journey through the queue:
55
+ // 1) position in the queue upon entry, and 2) whether spawning activity is occurring (which takes cycles
56
+ // but also indicates the server has headroom to handle the load).
57
+ Json::Value data;
58
+ if (!existingGroup) {
59
+ data["message"] = "spawning.."; // the first of this group, so keep it simple (also: we don't know maxQ yet)
60
+ } else {
61
+ char queueMaxStr[10];
62
+ int queueMax = existingGroup->options.maxRequestQueueSize;
63
+ if (queueMax > 0) {
64
+ snprintf(queueMaxStr, 10, "%d", queueMax);
65
+ }
66
+ char message[50];
67
+ snprintf(message, 100, "queue: %zu / %s, spawning: %s", existingGroup->getWaitlist.size(),
68
+ (queueMax == 0 ? "inf" : queueMaxStr),
69
+ (existingGroup->processesBeingSpawned == 0 ? "no" : "yes"));
70
+ data["message"] = message;
71
+ }
72
+ Json::Value json;
73
+ json["data"] = data;
74
+ json["data_type"] = "generic";
75
+ json["name"] = "Await available process";
76
+
77
+ *stopwatchLog = new UnionStation::StopwatchLog(options.transaction, "Pool::asyncGet", stringifyJson(json).c_str());
78
+ }
79
+
53
80
  if (OXT_LIKELY(existingGroup != NULL)) {
54
81
  /* Best case: the app group is already in the pool. Let's use it. */
55
82
  P_TRACE(2, "Found existing Group");
@@ -483,6 +483,9 @@ public:
483
483
  void forceMaxConcurrency(int value) {
484
484
  assert(value >= 0);
485
485
  concurrency = value;
486
+ for (unsigned i = 0; i < sessionSocketCount; i++) {
487
+ sessionSockets[i]->concurrency = concurrency;
488
+ }
486
489
  }
487
490
 
488
491
  void shutdownNotRequired() {
@@ -54,7 +54,7 @@ Controller::checkoutSession(Client *client, Request *req) {
54
54
  CC_BENCHMARK_POINT(client, req, BM_BEFORE_CHECKOUT);
55
55
  SKC_TRACE(client, 2, "Checking out session: appRoot=" << options.appRoot);
56
56
  req->state = Request::CHECKING_OUT_SESSION;
57
- req->beginStopwatchLog(&req->stopwatchLogs.getFromPool, "get from pool");
57
+
58
58
  if (req->requestBodyBuffering) {
59
59
  assert(!req->bodyBuffer.isStarted());
60
60
  } else {
@@ -70,7 +70,7 @@ Controller::checkoutSession(Client *client, Request *req) {
70
70
  #ifdef DEBUG_CC_EVENT_LOOP_BLOCKING
71
71
  req->timeBeforeAccessingApplicationPool = ev_now(getLoop());
72
72
  #endif
73
- appPool->asyncGet(options, callback);
73
+ appPool->asyncGet(options, callback, true, req->useUnionStation() ? &req->stopwatchLogs.getFromPool : NULL);
74
74
  #ifdef DEBUG_CC_EVENT_LOOP_BLOCKING
75
75
  if (!req->timedAppPoolGet) {
76
76
  req->timedAppPoolGet = true;
@@ -895,7 +895,7 @@ Controller::logResponseHeaders(Client *client, Request *req, struct iovec *buffe
895
895
  req->logMessage("Status: " + toString(req->appResponse.statusCode));
896
896
  }
897
897
 
898
- if (req->appResponse.statusCode >= 500 && req->appResponse.statusCode <= 599) {
898
+ if (req->appResponse.statusCode >= 400 && req->appResponse.statusCode <= 599) {
899
899
  // Log the request headers like Request headers: { header1: values1-concatenated, header2: values2-concatenated } (single line)
900
900
  // Concatenation was already done by HeaderTable.h:insert (using a comma ',' for joining, or a semicolon ';' for Cookie headers
901
901
  ServerKit::HeaderTable::Iterator it(req->headers);
@@ -140,9 +140,9 @@ public:
140
140
  return options.transaction != NULL;
141
141
  }
142
142
 
143
- void beginStopwatchLog(UnionStation::StopwatchLog **stopwatchLog, const char *name) {
143
+ void beginStopwatchLog(UnionStation::StopwatchLog **stopwatchLog, const char *id, const char *nameAndData = NULL) {
144
144
  if (options.transaction != NULL) {
145
- *stopwatchLog = new UnionStation::StopwatchLog(options.transaction, name);
145
+ *stopwatchLog = new UnionStation::StopwatchLog(options.transaction, id, nameAndData);
146
146
  }
147
147
  }
148
148
 
@@ -323,7 +323,7 @@ startListening() {
323
323
  #endif
324
324
 
325
325
  for (unsigned int i = 0; i < addresses.size(); i++) {
326
- wo->serverFds[i] = createServer(addresses[i], 0, true,
326
+ wo->serverFds[i] = createServer(addresses[i], agentsOptions->getInt("socket_backlog"), true,
327
327
  __FILE__, __LINE__);
328
328
  #ifdef USE_SELINUX
329
329
  resetSelinuxSocketContext();
@@ -790,7 +790,7 @@ static void
790
790
  abortLongRunningConnections(const ApplicationPool2::ProcessPtr &process) {
791
791
  // We are inside the ApplicationPool lock. Be very careful here.
792
792
  WorkingObjects *wo = workingObjects;
793
- P_NOTICE("Disconnecting long-running connections for process " <<
793
+ P_NOTICE("Checking whether to disconnect long-running connections for process " <<
794
794
  process->getPid() << ", application " << process->getGroup()->getName());
795
795
  for (unsigned int i = 0; i < wo->threadWorkingObjects.size(); i++) {
796
796
  wo->threadWorkingObjects[i].bgloop->safe->runLater(
@@ -1048,6 +1048,7 @@ setAgentsOptionsDefaults() {
1048
1048
  inferDefaultGroup(options.get("default_user")));
1049
1049
  }
1050
1050
  options.setDefaultStrSet("core_addresses", defaultAddress);
1051
+ options.setDefaultInt("socket_backlog", DEFAULT_SOCKET_BACKLOG);
1051
1052
  options.setDefaultBool("multi_app", false);
1052
1053
  options.setDefault("environment", DEFAULT_APP_ENV);
1053
1054
  options.setDefault("spawn_method", DEFAULT_SPAWN_METHOD);
@@ -65,6 +65,8 @@ coreUsage() {
65
65
  printf(" --api-listen ADDRESS Listen on the given address for API commands.\n");
66
66
  printf(" The same syntax and limitations as with --listen\n");
67
67
  printf(" are applicable\n");
68
+ printf(" --socket-backlog Override size of the socket backlog.\n");
69
+ printf(" Default: %d\n", DEFAULT_SOCKET_BACKLOG);
68
70
  printf("\n");
69
71
  printf("Daemon options (optional):\n");
70
72
  printf(" --pid-file PATH Store the core's PID in the given file. The file\n");
@@ -250,6 +252,9 @@ parseCoreOption(int argc, const char *argv[], int &i, VariantMap &options) {
250
252
  authorizations.push_back(argv[i + 1]);
251
253
  options.setStrSet("core_authorizations", authorizations);
252
254
  i += 2;
255
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--socket-backlog")) {
256
+ options.setInt("socket_backlog", atoi(argv[i + 1]));
257
+ i += 2;
253
258
  } else if (p.isFlag(argv[i], '\0', "--no-user-switching")) {
254
259
  options.setBool("user_switching", false);
255
260
  i++;