passenger 5.0.25 → 5.0.26
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 +4 -4
- data/CHANGELOG +20 -0
- data/CONTRIBUTORS +1 -0
- data/build/cxx_dependency_map.rb +7338 -7104
- data/build/cxx_tests.rb +3 -3
- data/build/misc.rb +1 -0
- data/dev/index_cxx_dependencies.rb +3 -2
- data/resources/templates/standalone/config.erb +1 -1
- data/resources/templates/standalone/http.erb +1 -0
- data/resources/templates/standalone/server.erb +1 -0
- data/src/agent/Core/ApplicationPool/AbstractSession.h +83 -0
- data/src/agent/Core/ApplicationPool/Common.h +6 -4
- data/src/agent/Core/ApplicationPool/Options.h +4 -1
- data/src/agent/Core/ApplicationPool/Pool.h +2 -2
- data/src/agent/Core/ApplicationPool/Pool/AnalyticsCollection.cpp +3 -6
- data/src/agent/Core/ApplicationPool/Pool/GeneralUtils.cpp +3 -3
- data/src/agent/Core/ApplicationPool/Session.h +15 -27
- data/src/agent/Core/ApplicationPool/TestSession.h +188 -0
- data/src/agent/Core/Controller.h +15 -6
- data/src/agent/Core/Controller/CheckoutSession.cpp +13 -5
- data/src/agent/Core/Controller/ForwardResponse.cpp +20 -2
- data/src/agent/Core/Controller/Hooks.cpp +15 -2
- data/src/agent/Core/Controller/InitRequest.cpp +5 -1
- data/src/agent/Core/Controller/InitializationAndShutdown.cpp +1 -0
- data/src/agent/Core/Controller/Request.h +11 -4
- data/src/agent/Core/Controller/SendRequest.cpp +34 -13
- data/src/agent/Core/Controller/StateInspectionAndConfiguration.cpp +2 -2
- data/src/agent/Core/CoreMain.cpp +27 -1
- data/src/agent/Core/OptionParser.h +11 -1
- data/src/agent/Core/SpawningKit/DirectSpawner.h +1 -0
- data/src/agent/Core/SpawningKit/SmartSpawner.h +1 -0
- data/src/agent/Core/SpawningKit/Spawner.h +21 -1
- data/src/agent/SpawnPreparer/SpawnPreparerMain.cpp +1 -1
- data/src/agent/UstRouter/OptionParser.h +7 -1
- data/src/agent/UstRouter/UstRouterMain.cpp +27 -1
- data/src/cxx_supportlib/Algorithms/MovingAverage.h +223 -0
- data/src/cxx_supportlib/Constants.h +2 -2
- data/src/cxx_supportlib/DataStructures/StringKeyTable.h +96 -40
- data/src/cxx_supportlib/ResourceLocator.h +33 -14
- data/src/cxx_supportlib/ServerKit/Channel.h +198 -69
- data/src/cxx_supportlib/ServerKit/Errors.h +6 -1
- data/src/cxx_supportlib/ServerKit/HttpRequest.h +20 -1
- data/src/cxx_supportlib/ServerKit/HttpServer.h +124 -32
- data/src/cxx_supportlib/ServerKit/Server.h +65 -1
- data/src/cxx_supportlib/Utils/IOUtils.cpp +12 -22
- data/src/cxx_supportlib/Utils/JsonUtils.h +87 -1
- data/src/cxx_supportlib/Utils/StrIntUtils.cpp +16 -1
- data/src/cxx_supportlib/Utils/StrIntUtils.h +31 -1
- data/src/cxx_supportlib/Utils/VariantMap.h +6 -1
- data/src/cxx_supportlib/WatchdogLauncher.h +17 -9
- data/src/cxx_supportlib/vendor-copy/libuv/AUTHORS +43 -0
- data/src/cxx_supportlib/vendor-copy/libuv/ChangeLog +350 -1
- data/src/cxx_supportlib/vendor-copy/libuv/Makefile.am +9 -1
- data/src/cxx_supportlib/vendor-copy/libuv/README.md +48 -0
- data/src/cxx_supportlib/vendor-copy/libuv/checksparse.sh +1 -0
- data/src/cxx_supportlib/vendor-copy/libuv/common.gypi +5 -5
- data/src/cxx_supportlib/vendor-copy/libuv/configure.ac +2 -1
- data/src/cxx_supportlib/vendor-copy/libuv/gyp_uv.py +0 -3
- data/src/cxx_supportlib/vendor-copy/libuv/include/uv-version.h +5 -1
- data/src/cxx_supportlib/vendor-copy/libuv/include/uv.h +30 -3
- data/src/cxx_supportlib/vendor-copy/libuv/src/fs-poll.c +3 -3
- data/src/cxx_supportlib/vendor-copy/libuv/src/inet.c +0 -4
- data/src/cxx_supportlib/vendor-copy/libuv/src/queue.h +17 -1
- data/src/cxx_supportlib/vendor-copy/libuv/src/threadpool.c +10 -10
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/aix.c +84 -166
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/android-ifaddrs.c +11 -11
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/async.c +7 -1
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/atomic-ops.h +17 -0
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/core.c +140 -21
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/darwin.c +15 -11
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/dl.c +4 -7
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/freebsd.c +52 -37
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/fs.c +181 -60
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/fsevents.c +39 -34
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/getaddrinfo.c +4 -4
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/internal.h +3 -1
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/kqueue.c +12 -4
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/linux-core.c +38 -15
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/linux-inotify.c +36 -8
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/linux-syscalls.c +4 -4
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/linux-syscalls.h +2 -2
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/loop-watcher.c +6 -1
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/loop.c +28 -8
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/netbsd.c +18 -16
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/openbsd.c +18 -16
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/pipe.c +3 -3
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/process.c +18 -6
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/proctitle.c +2 -2
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/pthread-fixes.c +1 -0
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/signal.c +2 -0
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/stream.c +47 -30
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/sunos.c +13 -11
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/tcp.c +43 -8
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/thread.c +21 -15
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/tty.c +16 -2
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/udp.c +54 -14
- data/src/cxx_supportlib/vendor-copy/libuv/src/uv-common.c +104 -21
- data/src/cxx_supportlib/vendor-copy/libuv/src/uv-common.h +14 -1
- data/src/cxx_supportlib/vendor-copy/libuv/src/version.c +1 -5
- data/src/cxx_supportlib/vendor-copy/libuv/uv.gyp +22 -1
- data/src/nginx_module/CacheLocationConfig.c +52 -0
- data/src/nginx_module/CacheLocationConfig.c.erb +13 -1
- data/src/nginx_module/Configuration.c +1 -0
- data/src/nginx_module/Configuration.h +1 -0
- data/src/nginx_module/ConfigurationCommands.c +20 -0
- data/src/nginx_module/ConfigurationFields.h +4 -0
- data/src/nginx_module/CreateLocationConfig.c +8 -0
- data/src/nginx_module/MergeLocationConfig.c +12 -0
- data/src/nginx_module/config +31 -13
- data/src/nginx_module/ngx_http_passenger_module.c +4 -0
- data/src/ruby_supportlib/phusion_passenger.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/constants.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +11 -1
- data/src/ruby_supportlib/phusion_passenger/platform_info/apache.rb +6 -1
- data/src/ruby_supportlib/phusion_passenger/rack/thread_handler_extension.rb +32 -31
- data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +13 -2
- data/src/ruby_supportlib/phusion_passenger/standalone/config_utils.rb +1 -0
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +6 -1
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core.rb +6 -0
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/api.rb +29 -19
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/context.rb +2 -2
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/request_reporter.rb +2 -3
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/simple_json.rb +2 -1
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/spec_helper.rb +2 -0
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/time_point.rb +3 -17
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/transaction.rb +7 -10
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/utils.rb +11 -9
- metadata +5 -2
data/src/agent/Core/Controller.h
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2011-
|
3
|
+
* Copyright (c) 2011-2016 Phusion Holding B.V.
|
4
4
|
*
|
5
5
|
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
6
|
* trademarks of Phusion Holding B.V.
|
@@ -119,6 +119,8 @@ private:
|
|
119
119
|
typedef ServerKit::FileBufferedChannel FileBufferedChannel;
|
120
120
|
typedef ServerKit::FileBufferedFdSinkChannel FileBufferedFdSinkChannel;
|
121
121
|
|
122
|
+
// If you change this value, make sure that Request::sessionCheckoutTry
|
123
|
+
// has enough bits.
|
122
124
|
static const unsigned int MAX_SESSION_CHECKOUT_TRY = 10;
|
123
125
|
|
124
126
|
unsigned int statThrottleRate;
|
@@ -218,12 +220,12 @@ private:
|
|
218
220
|
/****** Stage: checkout session ******/
|
219
221
|
|
220
222
|
void checkoutSession(Client *client, Request *req);
|
221
|
-
static void sessionCheckedOut(const
|
223
|
+
static void sessionCheckedOut(const AbstractSessionPtr &session,
|
222
224
|
const ExceptionPtr &e, void *userData);
|
223
225
|
void sessionCheckedOutFromAnotherThread(Client *client, Request *req,
|
224
|
-
|
226
|
+
AbstractSessionPtr session, ExceptionPtr e);
|
225
227
|
void sessionCheckedOutFromEventLoopThread(Client *client, Request *req,
|
226
|
-
const
|
228
|
+
const AbstractSessionPtr &session, const ExceptionPtr &e);
|
227
229
|
void maybeSend100Continue(Client *client, Request *req);
|
228
230
|
void initiateSession(Client *client, Request *req);
|
229
231
|
static void checkoutSessionLater(Request *req);
|
@@ -261,7 +263,7 @@ private:
|
|
261
263
|
void sendHeaderToAppWithHttpProtocolWithBuffering(Request *req, unsigned int offset,
|
262
264
|
HttpHeaderConstructionCache &cache);
|
263
265
|
void sendBodyToApp(Client *client, Request *req);
|
264
|
-
void
|
266
|
+
void maybeHalfCloseAppSinkBecauseRequestBodyEndReached(Client *client, Request *req);
|
265
267
|
Channel::Result whenSendingRequest_onRequestBody(Client *client, Request *req,
|
266
268
|
const MemoryKit::mbuf &buffer, int errcode);
|
267
269
|
static void resumeRequestBodyChannelWhenAppSinkIdle(Channel *_channel,
|
@@ -376,10 +378,17 @@ protected:
|
|
376
378
|
void deinitializeAppResponse(Client *client, Request *req);
|
377
379
|
virtual Channel::Result onRequestBody(Client *client, Request *req,
|
378
380
|
const MemoryKit::mbuf &buffer, int errcode);
|
381
|
+
virtual void onNextRequestEarlyReadError(Client *client, Request *req, int errcode);
|
379
382
|
virtual bool shouldDisconnectClientOnShutdown(Client *client);
|
380
383
|
virtual bool supportsUpgrade(Client *client, Request *req);
|
381
384
|
|
382
385
|
|
386
|
+
/****** Marked virtual so that unit tests can mock these ******/
|
387
|
+
|
388
|
+
virtual void asyncGetFromApplicationPool(Request *req,
|
389
|
+
ApplicationPool2::GetCallback callback);
|
390
|
+
|
391
|
+
|
383
392
|
public:
|
384
393
|
ResourceLocator *resourceLocator;
|
385
394
|
PoolPtr appPool;
|
@@ -390,7 +399,7 @@ public:
|
|
390
399
|
|
391
400
|
Controller(ServerKit::Context *context, const VariantMap *_agentsOptions,
|
392
401
|
unsigned int _threadNumber = 1);
|
393
|
-
~Controller();
|
402
|
+
virtual ~Controller();
|
394
403
|
void initialize();
|
395
404
|
|
396
405
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2011-
|
3
|
+
* Copyright (c) 2011-2016 Phusion Holding B.V.
|
4
4
|
*
|
5
5
|
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
6
|
* trademarks of Phusion Holding B.V.
|
@@ -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
|
-
|
73
|
+
asyncGetFromApplicationPool(req, callback);
|
74
74
|
#ifdef DEBUG_CC_EVENT_LOOP_BLOCKING
|
75
75
|
if (!req->timedAppPoolGet) {
|
76
76
|
req->timedAppPoolGet = true;
|
@@ -82,7 +82,15 @@ Controller::checkoutSession(Client *client, Request *req) {
|
|
82
82
|
}
|
83
83
|
|
84
84
|
void
|
85
|
-
Controller::
|
85
|
+
Controller::asyncGetFromApplicationPool(Request *req, ApplicationPool2::GetCallback callback) {
|
86
|
+
appPool->asyncGet(req->options, callback, true,
|
87
|
+
req->useUnionStation()
|
88
|
+
? &req->stopwatchLogs.getFromPool
|
89
|
+
: NULL);
|
90
|
+
}
|
91
|
+
|
92
|
+
void
|
93
|
+
Controller::sessionCheckedOut(const AbstractSessionPtr &session, const ExceptionPtr &e,
|
86
94
|
void *userData)
|
87
95
|
{
|
88
96
|
Request *req = static_cast<Request *>(userData);
|
@@ -101,7 +109,7 @@ Controller::sessionCheckedOut(const SessionPtr &session, const ExceptionPtr &e,
|
|
101
109
|
|
102
110
|
void
|
103
111
|
Controller::sessionCheckedOutFromAnotherThread(Client *client, Request *req,
|
104
|
-
|
112
|
+
AbstractSessionPtr session, ExceptionPtr e)
|
105
113
|
{
|
106
114
|
SKC_LOG_EVENT(Controller, client, "sessionCheckedOutFromAnotherThread");
|
107
115
|
sessionCheckedOutFromEventLoopThread(client, req, session, e);
|
@@ -110,7 +118,7 @@ Controller::sessionCheckedOutFromAnotherThread(Client *client, Request *req,
|
|
110
118
|
|
111
119
|
void
|
112
120
|
Controller::sessionCheckedOutFromEventLoopThread(Client *client, Request *req,
|
113
|
-
const
|
121
|
+
const AbstractSessionPtr &session, const ExceptionPtr &e)
|
114
122
|
{
|
115
123
|
if (req->ended()) {
|
116
124
|
return;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2011-
|
3
|
+
* Copyright (c) 2011-2016 Phusion Holding B.V.
|
4
4
|
*
|
5
5
|
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
6
|
* trademarks of Phusion Holding B.V.
|
@@ -295,6 +295,7 @@ Controller::onAppSourceData(Client *client, Request *req, const MemoryKit::mbuf
|
|
295
295
|
// EOF
|
296
296
|
UPDATE_TRACE_POINT();
|
297
297
|
SKC_TRACE(client, 2, "Application sent EOF");
|
298
|
+
SKC_TRACE(client, 2, "Not keep-aliving application session connection");
|
298
299
|
req->session->close(true, false);
|
299
300
|
endRequest(&client, &req);
|
300
301
|
return Channel::Result(0, false);
|
@@ -1078,7 +1079,24 @@ Controller::handleAppResponseBodyEnd(Client *client, Request *req) {
|
|
1078
1079
|
|
1079
1080
|
OXT_FORCE_INLINE void
|
1080
1081
|
Controller::keepAliveAppConnection(Client *client, Request *req) {
|
1081
|
-
req->
|
1082
|
+
if (req->halfClosePolicy == Request::HALF_CLOSE_PERFORMED) {
|
1083
|
+
SKC_TRACE(client, 2, "Not keep-aliving application session connection"
|
1084
|
+
" because it had been half-closed before");
|
1085
|
+
req->session->close(true, false);
|
1086
|
+
} else {
|
1087
|
+
// halfClosePolicy is initialized in sendHeaderToApp(). That method is
|
1088
|
+
// called immediately after checking out a session, before any events
|
1089
|
+
// from the appSource channel can be received.
|
1090
|
+
assert(req->halfClosePolicy != Request::HALF_CLOSE_POLICY_UNINITIALIZED);
|
1091
|
+
if (req->appResponse.wantKeepAlive) {
|
1092
|
+
SKC_TRACE(client, 2, "Keep-aliving application session connection");
|
1093
|
+
req->session->close(true, true);
|
1094
|
+
} else {
|
1095
|
+
SKC_TRACE(client, 2, "Not keep-aliving application session connection"
|
1096
|
+
" because application did not allow it");
|
1097
|
+
req->session->close(true, false);
|
1098
|
+
}
|
1099
|
+
}
|
1082
1100
|
}
|
1083
1101
|
|
1084
1102
|
void
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2011-
|
3
|
+
* Copyright (c) 2011-2016 Phusion Holding B.V.
|
4
4
|
*
|
5
5
|
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
6
|
* trademarks of Phusion Holding B.V.
|
@@ -129,8 +129,8 @@ Controller::reinitializeRequest(Client *client, Request *req) {
|
|
129
129
|
req->requestBodyBuffering = false;
|
130
130
|
req->https = false;
|
131
131
|
req->stickySession = false;
|
132
|
-
req->halfCloseAppConnection = false;
|
133
132
|
req->sessionCheckoutTry = 0;
|
133
|
+
req->halfClosePolicy = Request::HALF_CLOSE_POLICY_UNINITIALIZED;
|
134
134
|
req->appResponseInitialized = false;
|
135
135
|
req->strip100ContinueHeader = false;
|
136
136
|
req->hasPragmaHeader = false;
|
@@ -258,6 +258,19 @@ Controller::onRequestBody(Client *client, Request *req, const MemoryKit::mbuf &b
|
|
258
258
|
}
|
259
259
|
}
|
260
260
|
|
261
|
+
void
|
262
|
+
Controller::onNextRequestEarlyReadError(Client *client, Request *req, int errcode) {
|
263
|
+
ParentClass::onNextRequestEarlyReadError(client, req, errcode);
|
264
|
+
if (req->halfClosePolicy == Request::HALF_CLOSE_UPON_NEXT_REQUEST_EARLY_READ_ERROR) {
|
265
|
+
SKC_TRACE(client, 3, "Half-closing application socket with SHUT_WR"
|
266
|
+
" because the next request's early read error has been detected: "
|
267
|
+
<< ServerKit::getErrorDesc(errcode) << " (errno=" << errcode << ")");
|
268
|
+
req->halfClosePolicy = Request::HALF_CLOSE_PERFORMED;
|
269
|
+
assert(req->session != NULL);
|
270
|
+
::shutdown(req->session->fd(), SHUT_WR);
|
271
|
+
}
|
272
|
+
}
|
273
|
+
|
261
274
|
bool
|
262
275
|
Controller::shouldDisconnectClientOnShutdown(Client *client) {
|
263
276
|
return ParentClass::shouldDisconnectClientOnShutdown(client) || !gracefulExit;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2011-
|
3
|
+
* Copyright (c) 2011-2016 Phusion Holding B.V.
|
4
4
|
*
|
5
5
|
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
6
|
* trademarks of Phusion Holding B.V.
|
@@ -188,6 +188,9 @@ Controller::fillPoolOptionsFromAgentsOptions(Options &options) {
|
|
188
188
|
if (agentsOptions->has("meteor_app_settings")) {
|
189
189
|
options.meteorAppSettings = agentsOptions->get("meteor_app_settings");
|
190
190
|
}
|
191
|
+
if (agentsOptions->has("app_file_descriptor_ulimit")) {
|
192
|
+
options.fileDescriptorUlimit = agentsOptions->getUint("app_file_descriptor_ulimit");
|
193
|
+
}
|
191
194
|
|
192
195
|
options.logLevel = getLogLevel();
|
193
196
|
options.integrationMode = agentsOptions->get("integration_mode",
|
@@ -378,6 +381,7 @@ Controller::createNewPoolOptions(Client *client, Request *req,
|
|
378
381
|
fillPoolOption(req, options.restartDir, "!~PASSENGER_RESTART_DIR");
|
379
382
|
fillPoolOption(req, options.startupFile, "!~PASSENGER_STARTUP_FILE");
|
380
383
|
fillPoolOption(req, options.loadShellEnvvars, "!~PASSENGER_LOAD_SHELL_ENVVARS");
|
384
|
+
fillPoolOption(req, options.fileDescriptorUlimit, "!~PASSENGER_APP_FILE_DESCRIPTOR_ULIMIT");
|
381
385
|
fillPoolOption(req, options.raiseInternalError, "!~PASSENGER_RAISE_INTERNAL_ERROR");
|
382
386
|
/******************/
|
383
387
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2011-
|
3
|
+
* Copyright (c) 2011-2016 Phusion Holding B.V.
|
4
4
|
*
|
5
5
|
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
6
|
* trademarks of Phusion Holding B.V.
|
@@ -59,6 +59,13 @@ public:
|
|
59
59
|
WAITING_FOR_APP_OUTPUT
|
60
60
|
};
|
61
61
|
|
62
|
+
enum HalfClosePolicy {
|
63
|
+
HALF_CLOSE_POLICY_UNINITIALIZED,
|
64
|
+
HALF_CLOSE_UPON_REACHING_REQUEST_BODY_END,
|
65
|
+
HALF_CLOSE_UPON_NEXT_REQUEST_EARLY_READ_ERROR,
|
66
|
+
HALF_CLOSE_PERFORMED
|
67
|
+
};
|
68
|
+
|
62
69
|
ev_tstamp startedAt;
|
63
70
|
|
64
71
|
State state: 3;
|
@@ -66,16 +73,16 @@ public:
|
|
66
73
|
bool requestBodyBuffering: 1;
|
67
74
|
bool https: 1;
|
68
75
|
bool stickySession: 1;
|
69
|
-
bool halfCloseAppConnection: 1;
|
70
76
|
|
71
77
|
// Range: 0..MAX_SESSION_CHECKOUT_TRY
|
72
|
-
boost::uint8_t sessionCheckoutTry;
|
78
|
+
boost::uint8_t sessionCheckoutTry: 4;
|
79
|
+
HalfClosePolicy halfClosePolicy: 2;
|
73
80
|
bool appResponseInitialized: 1;
|
74
81
|
bool strip100ContinueHeader: 1;
|
75
82
|
bool hasPragmaHeader: 1;
|
76
83
|
|
77
84
|
Options options;
|
78
|
-
|
85
|
+
AbstractSessionPtr session;
|
79
86
|
const LString *host;
|
80
87
|
|
81
88
|
ServerKit::FdSinkChannel appSink;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2011-
|
3
|
+
* Copyright (c) 2011-2016 Phusion Holding B.V.
|
4
4
|
*
|
5
5
|
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
6
|
* trademarks of Phusion Holding B.V.
|
@@ -89,19 +89,38 @@ Controller::sendHeaderToApp(Client *client, Request *req) {
|
|
89
89
|
SKC_TRACE(client, 2, "Sending headers to application with " <<
|
90
90
|
req->session->getProtocol() << " protocol");
|
91
91
|
req->state = Request::SENDING_HEADER_TO_APP;
|
92
|
+
P_ASSERT_EQ(req->halfClosePolicy, Request::HALF_CLOSE_POLICY_UNINITIALIZED);
|
92
93
|
|
93
|
-
/**
|
94
|
-
* HTTP does not formally support half-closing, and Node.js treats a
|
95
|
-
* half-close as a full close, so we only half-close session sockets, not
|
96
|
-
* HTTP sockets.
|
97
|
-
*/
|
98
94
|
if (req->session->getProtocol() == "session") {
|
99
95
|
UPDATE_TRACE_POINT();
|
100
|
-
|
96
|
+
if (req->bodyType == Request::RBT_NO_BODY) {
|
97
|
+
// When there is no request body we will try to keep-alive the
|
98
|
+
// application connection, so half-close the application
|
99
|
+
// connection upon encountering the next request's early error
|
100
|
+
// in order not to break the keep-alive.
|
101
|
+
req->halfClosePolicy = Request::HALF_CLOSE_UPON_NEXT_REQUEST_EARLY_READ_ERROR;
|
102
|
+
} else {
|
103
|
+
// When there is a request body we won't try to keep-alive
|
104
|
+
// the application connection, so it's safe to half-close immediately
|
105
|
+
// upon reaching the end of the request body.
|
106
|
+
req->halfClosePolicy = Request::HALF_CLOSE_UPON_REACHING_REQUEST_BODY_END;
|
107
|
+
}
|
101
108
|
sendHeaderToAppWithSessionProtocol(client, req);
|
102
109
|
} else {
|
103
110
|
UPDATE_TRACE_POINT();
|
104
|
-
req->
|
111
|
+
if (req->bodyType == Request::RBT_UPGRADE) {
|
112
|
+
req->halfClosePolicy = Request::HALF_CLOSE_UPON_REACHING_REQUEST_BODY_END;
|
113
|
+
} else {
|
114
|
+
// HTTP does not formally support half-closing. Some apps support
|
115
|
+
// HTTP with half-closing, others (such as Node.js http.Server with
|
116
|
+
// default settings) treat a half-close as a full close. Furthermore,
|
117
|
+
// we always try to keep-alive the application connection.
|
118
|
+
//
|
119
|
+
// So we can't half-close immediately upon reaching the end of the
|
120
|
+
// request body. The app might not have yet sent a response by then.
|
121
|
+
// We only half-close upon the next request's early error.
|
122
|
+
req->halfClosePolicy = Request::HALF_CLOSE_UPON_NEXT_REQUEST_EARLY_READ_ERROR;
|
123
|
+
}
|
105
124
|
sendHeaderToAppWithHttpProtocol(client, req);
|
106
125
|
}
|
107
126
|
|
@@ -944,15 +963,17 @@ Controller::sendBodyToApp(Client *client, Request *req) {
|
|
944
963
|
// data is forwarded.
|
945
964
|
SKC_TRACE(client, 2, "No body to send to application");
|
946
965
|
req->state = Request::WAITING_FOR_APP_OUTPUT;
|
947
|
-
|
966
|
+
maybeHalfCloseAppSinkBecauseRequestBodyEndReached(client, req);
|
948
967
|
}
|
949
968
|
}
|
950
969
|
|
951
970
|
void
|
952
|
-
Controller::
|
971
|
+
Controller::maybeHalfCloseAppSinkBecauseRequestBodyEndReached(Client *client, Request *req) {
|
953
972
|
P_ASSERT_EQ(req->state, Request::WAITING_FOR_APP_OUTPUT);
|
954
|
-
if (req->
|
955
|
-
SKC_TRACE(client, 3, "Half-closing application socket with SHUT_WR"
|
973
|
+
if (req->halfClosePolicy == Request::HALF_CLOSE_UPON_REACHING_REQUEST_BODY_END) {
|
974
|
+
SKC_TRACE(client, 3, "Half-closing application socket with SHUT_WR"
|
975
|
+
" because end of request body reached");
|
976
|
+
req->halfClosePolicy = Request::HALF_CLOSE_PERFORMED;
|
956
977
|
::shutdown(req->session->fd(), SHUT_WR);
|
957
978
|
}
|
958
979
|
}
|
@@ -1007,7 +1028,7 @@ Controller::whenSendingRequest_onRequestBody(Client *client, Request *req,
|
|
1007
1028
|
// care of ending the request, once all response
|
1008
1029
|
// data is forwarded.
|
1009
1030
|
req->state = Request::WAITING_FOR_APP_OUTPUT;
|
1010
|
-
|
1031
|
+
maybeHalfCloseAppSinkBecauseRequestBodyEndReached(client, req);
|
1011
1032
|
return Channel::Result(0, true);
|
1012
1033
|
} else {
|
1013
1034
|
const unsigned int BUFSIZE = 1024;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2014-
|
3
|
+
* Copyright (c) 2014-2016 Phusion Holding B.V.
|
4
4
|
*
|
5
5
|
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
6
|
* trademarks of Phusion Holding B.V.
|
@@ -117,7 +117,7 @@ Controller::inspectRequestStateAsJson(const Request *req) const {
|
|
117
117
|
|
118
118
|
if (req->session != NULL) {
|
119
119
|
Json::Value &sessionDoc = doc["session"] = Json::Value(Json::objectValue);
|
120
|
-
const
|
120
|
+
const AbstractSession *session = req->session.get();
|
121
121
|
|
122
122
|
if (req->session->isClosed()) {
|
123
123
|
sessionDoc["closed"] = true;
|
data/src/agent/Core/CoreMain.cpp
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2010-
|
3
|
+
* Copyright (c) 2010-2016 Phusion Holding B.V.
|
4
4
|
*
|
5
5
|
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
6
|
* trademarks of Phusion Holding B.V.
|
@@ -40,6 +40,7 @@
|
|
40
40
|
#include <sys/socket.h>
|
41
41
|
#include <sys/stat.h>
|
42
42
|
#include <sys/un.h>
|
43
|
+
#include <sys/resource.h>
|
43
44
|
#include <cstring>
|
44
45
|
#include <cassert>
|
45
46
|
#include <cerrno>
|
@@ -259,6 +260,30 @@ initializeSingleAppMode() {
|
|
259
260
|
P_NOTICE("App startup file: " << options.get("startup_file"));
|
260
261
|
}
|
261
262
|
|
263
|
+
static void
|
264
|
+
setUlimits() {
|
265
|
+
TRACE_POINT();
|
266
|
+
VariantMap &options = *agentsOptions;
|
267
|
+
|
268
|
+
if (options.has("core_file_descriptor_ulimit")) {
|
269
|
+
unsigned int number = options.getUint("core_file_descriptor_ulimit");
|
270
|
+
struct rlimit limit;
|
271
|
+
int ret;
|
272
|
+
|
273
|
+
limit.rlim_cur = number;
|
274
|
+
limit.rlim_max = number;
|
275
|
+
do {
|
276
|
+
ret = setrlimit(RLIMIT_NOFILE, &limit);
|
277
|
+
} while (ret == -1 && errno == EINTR);
|
278
|
+
|
279
|
+
if (ret == -1) {
|
280
|
+
int e = errno;
|
281
|
+
P_ERROR("Unable to set file descriptor ulimit to " << number
|
282
|
+
<< ": " << strerror(e) << " (errno=" << e << ")");
|
283
|
+
}
|
284
|
+
}
|
285
|
+
}
|
286
|
+
|
262
287
|
static void
|
263
288
|
makeFileWorldReadableAndWritable(const string &path) {
|
264
289
|
int ret;
|
@@ -960,6 +985,7 @@ runCore() {
|
|
960
985
|
UPDATE_TRACE_POINT();
|
961
986
|
initializePrivilegedWorkingObjects();
|
962
987
|
initializeSingleAppMode();
|
988
|
+
setUlimits();
|
963
989
|
startListening();
|
964
990
|
createPidFile();
|
965
991
|
lowerPrivilege();
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2010-
|
3
|
+
* Copyright (c) 2010-2016 Phusion Holding B.V.
|
4
4
|
*
|
5
5
|
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
6
|
* trademarks of Phusion Holding B.V.
|
@@ -118,6 +118,8 @@ coreUsage() {
|
|
118
118
|
printf(" --meteor-app-settings PATH\n");
|
119
119
|
printf(" File with settings for a Meteor (non-bundled) app.\n");
|
120
120
|
printf(" (passed to Meteor using --settings)\n");
|
121
|
+
printf(" --app-file-descriptor-ulimit NUMBER\n");
|
122
|
+
printf(" Set custom file descriptor ulimit for the app\n");
|
121
123
|
printf(" --debugger Enable Ruby debugger support (Enterprise only)\n");
|
122
124
|
printf("\n");
|
123
125
|
printf(" --rolling-restarts Enable rolling restarts (Enterprise only)\n");
|
@@ -185,6 +187,8 @@ coreUsage() {
|
|
185
187
|
printf(" Default: number of CPU cores (%d)\n",
|
186
188
|
boost::thread::hardware_concurrency());
|
187
189
|
printf(" --cpu-affine Enable per-thread CPU affinity (Linux only)\n");
|
190
|
+
printf(" --core-file-descriptor-ulimit NUMBER\n");
|
191
|
+
printf(" Set custom file descriptor ulimit for the core\n");
|
188
192
|
printf(" -h, --help Show this help\n");
|
189
193
|
printf("\n");
|
190
194
|
printf("API account privilege levels (ordered from most to least privileges):\n");
|
@@ -345,6 +349,9 @@ parseCoreOption(int argc, const char *argv[], int &i, VariantMap &options) {
|
|
345
349
|
} else if (p.isValueFlag(argc, i, argv[i], '\0', "--meteor-app-settings")) {
|
346
350
|
options.set("meteor_app_settings", argv[i + 1]);
|
347
351
|
i += 2;
|
352
|
+
} else if (p.isValueFlag(argc, i, argv[i], '\0', "--app-file-descriptor-ulimit")) {
|
353
|
+
options.setUint("app_file_descriptor_ulimit", atoi(argv[i + 1]));
|
354
|
+
i += 2;
|
348
355
|
} else if (p.isFlag(argv[i], '\0', "--debugger")) {
|
349
356
|
options.setBool("debugger", true);
|
350
357
|
i++;
|
@@ -393,6 +400,9 @@ parseCoreOption(int argc, const char *argv[], int &i, VariantMap &options) {
|
|
393
400
|
} else if (p.isFlag(argv[i], '\0', "--cpu-affine")) {
|
394
401
|
options.setBool("core_cpu_affine", true);
|
395
402
|
i++;
|
403
|
+
} else if (p.isValueFlag(argc, i, argv[i], '\0', "--core-file-descriptor-ulimit")) {
|
404
|
+
options.setUint("core_file_descriptor_ulimit", atoi(argv[i + 1]));
|
405
|
+
i += 2;
|
396
406
|
} else if (!startsWith(argv[i], "-")) {
|
397
407
|
if (!options.has("app_root")) {
|
398
408
|
options.set("app_root", argv[i]);
|