passenger 5.0.2 → 5.0.3
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 +8 -8
- checksums.yaml.gz.asc +7 -7
- data.tar.gz.asc +7 -7
- data/CHANGELOG +16 -1
- data/build/cxx_tests.rb +3 -0
- data/build/packaging.rb +5 -5
- data/doc/Users guide Nginx.txt +0 -3
- data/doc/users_guide_snippets/tips.txt +3 -2
- data/ext/common/Constants.h +1 -1
- data/ext/common/Hooks.h +1 -0
- data/ext/common/Logging.cpp +19 -12
- data/ext/common/ServerKit/AcceptLoadBalancer.h +74 -16
- data/ext/common/ServerKit/Server.h +3 -1
- data/ext/common/Utils/StrIntUtils.cpp +33 -1
- data/ext/common/Utils/StrIntUtils.h +9 -1
- data/ext/common/Utils/jsoncpp.cpp +5 -0
- data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +10 -2
- data/ext/common/agents/HelperAgent/RequestHandler/SendRequest.cpp +5 -1
- data/ext/common/agents/HelperAgent/RequestHandler/TurboCaching.h +2 -2
- data/ext/common/agents/Watchdog/Main.cpp +2 -0
- data/lib/phusion_passenger.rb +1 -1
- data/lib/phusion_passenger/config/about_command.rb +7 -2
- data/lib/phusion_passenger/rack/thread_handler_extension.rb +9 -13
- data/lib/phusion_passenger/standalone/start_command/builtin_engine.rb +3 -4
- data/test/cxx/Utils/StrIntUtilsTest.cpp +39 -0
- metadata +3 -2
- metadata.gz.asc +7 -7
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YjRiYzNlNmYwZDQ5OGQ5MjJhMmE2MjM2MDE5M2M1YTBmMWVjNzAyOQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
OTBjODU4Yjg5OTUzOGJlMzIxOGE5YjVmODY5ZTFhOGUzMGM3MmI0OQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YTEyMmZkOWViYjU4YjNkNzA3M2VkNjA1MTgzMTdmMzUxYjc2MjlhYTA1MGM1
|
10
|
+
N2YzYWE3NjllZjcwNjQ5MjcxYTEyMWRkZDdhYzZmMWFiODJjMzU3ZGE0NTJk
|
11
|
+
OWY0OGU0MDU4ZTc5NWY5NTg5MmJlZDBiODJkYTQ4Y2M1MDVhMzU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YTY0NWM0M2FmOWU1ZDVmZjJkNjhmZDE4MThkNjM1YjNhNTNiNzcxZDU2MzRm
|
14
|
+
OGFiOTZiODBmMjJjMjMwOGJkZjliOTA3Mzg5OGE3N2E3ODNmNmZmNGEzMjI5
|
15
|
+
MDMyZDYwYWJiYzI4MDI4YmMwMzRjYmQwYzA4NTlmODE2YzVjZmY=
|
checksums.yaml.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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
=
|
5
|
+
iQEcBAABAgAGBQJVAMF1AAoJECrHRaUKISqMDSsH/0xm2Y70Fr8iahHgf2MSe/bv
|
6
|
+
jKAkjl+MqArHlEcAskMRSwYoOJRRTbAYF8R7WxAJERnpCEa1a9l1bVO3DMCprDD7
|
7
|
+
by1xGn2FW2WWcsQcWjPNSeTgdII7qPtxk3AJ9KTP8PEoxMjzZKpBzCxHiwOTJ64t
|
8
|
+
7AAGqEJ5Cr8zFq17NA9Lm9h8wvk7uop5ejmGJmgaOAcxtzowSXhGmN37C1yGGVWI
|
9
|
+
wUl5d2etK8vRry7T+bxL8eTn8e4fmcJXjk/Jq7Bq35YSR6lhUwPT/5GBe7ENrR4s
|
10
|
+
0E7sOLTuROhGsKpJ0SFvkSiywS/rldjxut1wzjDWmmB6tnEb4gdtZ4JuWHuDPPQ=
|
11
|
+
=bM1v
|
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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
=
|
5
|
+
iQEcBAABAgAGBQJVAMF1AAoJECrHRaUKISqMYNMIAK47UJTr5fLogoJ8+cF++oT4
|
6
|
+
jIyexyKyXXlySoUHBFBwSikqAWrpVnZPCDu4ULUHSTDPHy/jkcfcC6LYzmtq0AiN
|
7
|
+
NagWHqhtklUNgBoWUfv4rEg05hoZOUbFNysp2zbcQvqFEjhmNUONXnWzOgd1UMIC
|
8
|
+
wNxZVHxnVpmmnDqc0zfE4CTTcSSc98BLMX3xaWP3bzKHFuM0UvXczTdcgdnhOxrf
|
9
|
+
+wJ7Fp8i2YA7yADEYp8aMX1jUIB/UuhTQ5qjG+4whpMfGQvDqJpmh2Z9lolQPxv/
|
10
|
+
skt34/MboC5CuRq1jpJ40kU3P5XqY5XKe5sWdlC0z3lhiTXNcUA5hvOB1ZOIukc=
|
11
|
+
=oRka
|
12
12
|
-----END PGP SIGNATURE-----
|
data/CHANGELOG
CHANGED
@@ -1,8 +1,23 @@
|
|
1
|
+
Release 5.0.3
|
2
|
+
-------------
|
3
|
+
|
4
|
+
* [Standalone] When using the builtin engine, `passenger start` may crash during startup due to an initialization race condition. This has been fixed.
|
5
|
+
* [Enterprise] Fixes a bug in passenger-irb. Running passenger-irb without a PID parameter worked, but running it with a PID parameter didn't.
|
6
|
+
* Fixes an integer overflow that resulted in a file descriptor leak and stalled client connections. Closes GH-1412.
|
7
|
+
* Truncates Passenger source code paths in logs (to 3 chars) to reduce redundant info. Closes GH-1383.
|
8
|
+
* Fixes invalid JSON output for non-finite double values (e.g. from the HTTP JSON API). Closes GH-1408.
|
9
|
+
* All hooks now set the `PASSENGER_HOOK_NAME` environment variable. This variable is set to the name of the hook that is being called.
|
10
|
+
* The Ruby handler no longer tries to call #force_encoding on response body strings, which fixes an incompatibility with apps/libraries that return frozen body strings. Closes GH-1414.
|
11
|
+
* If the Ruby handler crashes while processing a Rack response body, it will now no longer stall the connection.
|
12
|
+
* Fixes env.SERVER_PORT containing 80 instead of 443 when using https on default port. Closes GH-1421.
|
13
|
+
* We now handle errors in the `poll()` system call better. This might fix some crashes during shutdown which manifest on FreeBSD.
|
14
|
+
|
15
|
+
|
1
16
|
Release 5.0.2
|
2
17
|
-------------
|
3
18
|
|
4
19
|
* Fixes a connection freeze that could occur when processing large responses. This would manifest itself under the error message "This website is under heavy load" or "Request queue is full, returning an error". Closes GH-1404.
|
5
|
-
* Debian and Ubuntu packages have been
|
20
|
+
* Debian and Ubuntu packages have been reintroduced.
|
6
21
|
* When `passenger-config restart-app` is run interactively, if Passenger is not serving any applications, then the command now prints an error message instead of showing a menu with only a "Cancel" option.
|
7
22
|
* Fixes a compilation problem on FreeBSD 10 (contributed by: clemensg). Closes GH-1401.
|
8
23
|
* [Standalone] Fixes a crash that would occur if you use the `--ctl` parameter.
|
data/build/cxx_tests.rb
CHANGED
@@ -249,6 +249,9 @@ TEST_CXX_OBJECTS = {
|
|
249
249
|
'test/cxx/UtilsTest.o' => %w(
|
250
250
|
test/cxx/UtilsTest.cpp
|
251
251
|
ext/common/Utils.h),
|
252
|
+
'test/cxx/Utils/StrIntUtilsTest.o' => %w(
|
253
|
+
test/cxx/Utils/StrIntUtilsTest.cpp
|
254
|
+
ext/common/Utils/StrIntUtils.cpp),
|
252
255
|
'test/cxx/IOUtilsTest.o' => %w(
|
253
256
|
test/cxx/IOUtilsTest.cpp
|
254
257
|
ext/common/Utils/IOUtils.h),
|
data/build/packaging.rb
CHANGED
@@ -318,10 +318,10 @@ task 'package:sign' do
|
|
318
318
|
end
|
319
319
|
|
320
320
|
task 'package:update_homebrew' do
|
321
|
-
require 'digest/
|
321
|
+
require 'digest/sha2'
|
322
322
|
version = VERSION_STRING
|
323
|
-
|
324
|
-
Digest::
|
323
|
+
sha256 = File.open("#{PKG_DIR}/passenger-#{version}.tar.gz", "rb") do |f|
|
324
|
+
Digest::SHA256.hexdigest(f.read)
|
325
325
|
end
|
326
326
|
sh "rm -rf #{homebrew_dir}"
|
327
327
|
sh "git clone git@github.com:phusion/homebrew.git #{homebrew_dir}"
|
@@ -331,8 +331,8 @@ task 'package:update_homebrew' do
|
|
331
331
|
formula = File.read("/tmp/homebrew/Library/Formula/passenger.rb")
|
332
332
|
formula.gsub!(/passenger-.+?\.tar\.gz/, "passenger-#{version}.tar.gz") ||
|
333
333
|
abort("Unable to substitute Homebrew formula tarball filename")
|
334
|
-
formula.gsub!(/^
|
335
|
-
abort("Unable to substitute Homebrew formula SHA-
|
334
|
+
formula.gsub!(/^ sha256 .*/, " sha256 '#{sha256}'") ||
|
335
|
+
abort("Unable to substitute Homebrew formula SHA-256")
|
336
336
|
necessary_dirs = ORIG_TARBALL_FILES.call.map{ |filename| filename.split("/").first }.uniq
|
337
337
|
necessary_dirs -= Packaging::HOMEBREW_EXCLUDE
|
338
338
|
necessary_dirs += ["buildout"]
|
data/doc/Users guide Nginx.txt
CHANGED
@@ -1242,9 +1242,6 @@ This option may occur in the following places:
|
|
1242
1242
|
|
1243
1243
|
In each place, it may be specified at most once. The default value is '300' (5 minutes).
|
1244
1244
|
|
1245
|
-
:option: `--max-preloader-idle-time`
|
1246
|
-
include::users_guide_snippets/alternative_for_flying_passenger.txt[]
|
1247
|
-
|
1248
1245
|
==== passenger_start_timeout <seconds> ====
|
1249
1246
|
:version: 4.0.15
|
1250
1247
|
include::users_guide_snippets/since_version.txt[]
|
@@ -453,10 +453,11 @@ A lot of information is passed to hook scripts in the form of environment variab
|
|
453
453
|
|
454
454
|
Here are some of the environment variables which are passed to all hooks, unless documented otherwise:
|
455
455
|
|
456
|
+
* `PASSENGER_HOOK_NAME`
|
456
457
|
* `PASSENGER_VERSION`
|
457
458
|
* `PASSENGER_PASSENGER_ROOT`
|
458
|
-
* `
|
459
|
-
* `
|
459
|
+
* `PASSENGER_INSTANCE_DIR`
|
460
|
+
* `PASSENGER_INSTANCE_REGISTRY_DIR`
|
460
461
|
|
461
462
|
==== Blocking and concurrency
|
462
463
|
|
data/ext/common/Constants.h
CHANGED
data/ext/common/Hooks.h
CHANGED
data/ext/common/Logging.cpp
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2010-
|
3
|
+
* Copyright (c) 2010-2015 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -42,6 +42,8 @@ AssertionFailureInfo lastAssertionFailure;
|
|
42
42
|
static bool printAppOutputAsDebuggingMessages = false;
|
43
43
|
static char *logFile = NULL;
|
44
44
|
|
45
|
+
#define TRUNCATE_LOGPATHS_TO_MAXCHARS 3 // set to 0 to disable truncation
|
46
|
+
|
45
47
|
void
|
46
48
|
setLogLevel(int value) {
|
47
49
|
_logLevel = value;
|
@@ -87,16 +89,6 @@ _prepareLogEntry(std::stringstream &sstream, const char *file, unsigned int line
|
|
87
89
|
char datetime_buf[60];
|
88
90
|
struct timeval tv;
|
89
91
|
|
90
|
-
if (startsWith(file, "ext/")) {
|
91
|
-
file += sizeof("ext/") - 1;
|
92
|
-
if (startsWith(file, "common/")) {
|
93
|
-
file += sizeof("common/") - 1;
|
94
|
-
if (startsWith(file, "ApplicationPool2/")) {
|
95
|
-
file += sizeof("Application") - 1;
|
96
|
-
}
|
97
|
-
}
|
98
|
-
}
|
99
|
-
|
100
92
|
the_time = time(NULL);
|
101
93
|
localtime_r(&the_time, &the_tm);
|
102
94
|
strftime(datetime_buf, sizeof(datetime_buf) - 1, "%F %H:%M:%S", &the_tm);
|
@@ -106,7 +98,22 @@ _prepareLogEntry(std::stringstream &sstream, const char *file, unsigned int line
|
|
106
98
|
(unsigned long) (tv.tv_usec / 100) <<
|
107
99
|
" " << std::dec << getpid() << "/" <<
|
108
100
|
std::hex << pthread_self() << std::dec <<
|
109
|
-
" "
|
101
|
+
" ";
|
102
|
+
|
103
|
+
if (startsWith(file, "ext/")) { // special reduncancy filter because most code resides in these paths
|
104
|
+
file += sizeof("ext/") - 1;
|
105
|
+
if (startsWith(file, "common/")) {
|
106
|
+
file += sizeof("common/") - 1;
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
if (TRUNCATE_LOGPATHS_TO_MAXCHARS > 0) {
|
111
|
+
truncateBeforeTokens(file, "/\\", TRUNCATE_LOGPATHS_TO_MAXCHARS, sstream);
|
112
|
+
} else {
|
113
|
+
sstream << file;
|
114
|
+
}
|
115
|
+
|
116
|
+
sstream << ":" << line <<
|
110
117
|
" ]: ";
|
111
118
|
}
|
112
119
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2014 Phusion
|
3
|
+
* Copyright (c) 2014-2015 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -26,9 +26,12 @@
|
|
26
26
|
#define _PASSENGER_SERVER_KIT_ACCEPT_LOAD_BALANCER_H_
|
27
27
|
|
28
28
|
#include <boost/bind.hpp>
|
29
|
+
#include <boost/cstdint.hpp>
|
30
|
+
#include <boost/config.hpp>
|
29
31
|
#include <oxt/thread.hpp>
|
30
32
|
#include <oxt/macros.hpp>
|
31
33
|
#include <vector>
|
34
|
+
#include <limits>
|
32
35
|
#include <cassert>
|
33
36
|
#include <cerrno>
|
34
37
|
|
@@ -41,6 +44,7 @@
|
|
41
44
|
|
42
45
|
#include <Constants.h>
|
43
46
|
#include <Logging.h>
|
47
|
+
#include <Utils.h>
|
44
48
|
#include <Utils/IOUtils.h>
|
45
49
|
|
46
50
|
namespace Passenger {
|
@@ -50,6 +54,32 @@ using namespace std;
|
|
50
54
|
using namespace boost;
|
51
55
|
|
52
56
|
|
57
|
+
/**
|
58
|
+
* Listens for client connections and load balances them to multiple
|
59
|
+
* Server objects in a round-robin manner.
|
60
|
+
*
|
61
|
+
* Normally, the Server class listens for client connections directly.
|
62
|
+
* But this is inefficient in multithreaded situations where you are
|
63
|
+
* running one Server and event loop per CPU core, that all happen to
|
64
|
+
* listen on the same server socket. This is because every time a client
|
65
|
+
* connects, all threads wake up, but only one thread will succeed in
|
66
|
+
* accept()ing the client.
|
67
|
+
*
|
68
|
+
* Furthermore, it can also be very easy for threads to become
|
69
|
+
* unbalanced. If a burst of clients connect to the server socket,
|
70
|
+
* then it is very likely that a single Server accepts all of
|
71
|
+
* those clients. This can result in situations where, for example,
|
72
|
+
* thread 1 has 40 clients and thread 2 has only 3.
|
73
|
+
*
|
74
|
+
* The AcceptLoadBalancer solves this problem by being the sole entity
|
75
|
+
* that listens on the server socket. All client sockets that it
|
76
|
+
* accepts are distributed to all registered Server objects, in a
|
77
|
+
* round-robin manner.
|
78
|
+
*
|
79
|
+
* Inside the "PassengerAgent server", we activate AcceptLoadBalancer
|
80
|
+
* only if `server_threads > 1`, which is often the case because
|
81
|
+
* `server_threads` defaults to the number of CPU cores.
|
82
|
+
*/
|
53
83
|
template<typename Server>
|
54
84
|
class AcceptLoadBalancer {
|
55
85
|
private:
|
@@ -59,15 +89,24 @@ private:
|
|
59
89
|
struct pollfd pollers[1 + SERVER_KIT_MAX_SERVER_ENDPOINTS];
|
60
90
|
int newClients[ACCEPT_BURST_COUNT];
|
61
91
|
|
62
|
-
unsigned int nEndpoints
|
63
|
-
|
64
|
-
|
65
|
-
|
92
|
+
unsigned int nEndpoints;
|
93
|
+
boost::uint8_t newClientCount;
|
94
|
+
boost::uint8_t nextServer;
|
95
|
+
bool accept4Available;
|
96
|
+
bool quit;
|
66
97
|
|
67
|
-
unsigned int nextServer;
|
68
98
|
int exitPipe[2];
|
69
99
|
oxt::thread *thread;
|
70
100
|
|
101
|
+
#if __cplusplus >= 199711L && !defined(BOOST_NO_STATIC_ASSERT)
|
102
|
+
static_assert(std::numeric_limits<typeof(nEndpoints)>::max()
|
103
|
+
>= SERVER_KIT_MAX_SERVER_ENDPOINTS,
|
104
|
+
"nEndpoints's type is too small to accomodate for SERVER_KIT_MAX_SERVER_ENDPOINTS");
|
105
|
+
static_assert(std::numeric_limits<typeof(newClientCount)>::max()
|
106
|
+
>= ACCEPT_BURST_COUNT,
|
107
|
+
"newClientCount's type is too small to accomodate for ACCEPT_BURST_COUNT");
|
108
|
+
#endif
|
109
|
+
|
71
110
|
void pollAllEndpoints() {
|
72
111
|
pollers[0].fd = exitPipe[0];
|
73
112
|
pollers[0].events = POLLIN;
|
@@ -75,18 +114,28 @@ private:
|
|
75
114
|
pollers[i + 1].fd = endpoints[i];
|
76
115
|
pollers[i + 1].events = POLLIN;
|
77
116
|
}
|
78
|
-
|
117
|
+
|
118
|
+
int ret;
|
119
|
+
do {
|
120
|
+
ret = poll(pollers, nEndpoints + 1, -1) == -1;
|
121
|
+
} while (ret == -1 && pollErrnoShouldRetry(errno));
|
122
|
+
if (ret == -1) {
|
79
123
|
int e = errno;
|
80
124
|
throw SystemException("poll() failed", e);
|
81
125
|
}
|
82
126
|
}
|
83
127
|
|
128
|
+
bool pollErrnoShouldRetry(int e) const {
|
129
|
+
return e == EAGAIN
|
130
|
+
|| e == EWOULDBLOCK
|
131
|
+
|| e == EINTR;
|
132
|
+
}
|
133
|
+
|
84
134
|
bool acceptNewClients(int endpoint) {
|
85
|
-
unsigned int i;
|
86
135
|
bool error = false;
|
87
136
|
int fd, errcode = 0;
|
88
137
|
|
89
|
-
|
138
|
+
while (newClientCount < ACCEPT_BURST_COUNT) {
|
90
139
|
fd = acceptNonBlockingSocket(endpoint);
|
91
140
|
if (fd == -1) {
|
92
141
|
error = true;
|
@@ -94,11 +143,11 @@ private:
|
|
94
143
|
break;
|
95
144
|
}
|
96
145
|
|
97
|
-
|
146
|
+
P_TRACE(2, "Accepted client file descriptor: " << fd);
|
147
|
+
newClients[newClientCount] = fd;
|
148
|
+
newClientCount++;
|
98
149
|
}
|
99
150
|
|
100
|
-
newClientCount = i;
|
101
|
-
|
102
151
|
if (error && errcode != EAGAIN && errcode != EWOULDBLOCK) {
|
103
152
|
P_ERROR("Cannot accept client: " << getErrorDesc(errcode) <<
|
104
153
|
" (errno=" << errcode << "). " <<
|
@@ -121,6 +170,8 @@ private:
|
|
121
170
|
|
122
171
|
for (i = 0; i < newClientCount; i++) {
|
123
172
|
ServerKit::Context *ctx = servers[nextServer]->getContext();
|
173
|
+
P_TRACE(2, "Feeding client to server thread " << nextServer <<
|
174
|
+
": file descriptor " << newClients[i]);
|
124
175
|
ctx->libev->runLater(boost::bind(feedNewClient, servers[nextServer],
|
125
176
|
newClients[i]));
|
126
177
|
nextServer = (nextServer + 1) % servers.size();
|
@@ -182,13 +233,19 @@ private:
|
|
182
233
|
quit = true;
|
183
234
|
break;
|
184
235
|
}
|
185
|
-
|
236
|
+
|
237
|
+
unsigned int i = 0;
|
238
|
+
newClientCount = 0;
|
239
|
+
|
240
|
+
while (newClientCount < ACCEPT_BURST_COUNT && i < nEndpoints) {
|
186
241
|
if (pollers[i + 1].revents & POLLIN) {
|
187
242
|
if (!acceptNewClients(endpoints[i])) {
|
188
243
|
break;
|
189
244
|
}
|
190
245
|
}
|
246
|
+
i++;
|
191
247
|
}
|
248
|
+
|
192
249
|
distributeNewClients();
|
193
250
|
}
|
194
251
|
}
|
@@ -198,10 +255,10 @@ public:
|
|
198
255
|
|
199
256
|
AcceptLoadBalancer()
|
200
257
|
: nEndpoints(0),
|
201
|
-
accept4Available(true),
|
202
|
-
quit(false),
|
203
258
|
newClientCount(0),
|
204
259
|
nextServer(0),
|
260
|
+
accept4Available(true),
|
261
|
+
quit(false),
|
205
262
|
thread(NULL)
|
206
263
|
{
|
207
264
|
if (pipe(exitPipe) == -1) {
|
@@ -248,7 +305,8 @@ public:
|
|
248
305
|
}
|
249
306
|
|
250
307
|
void start() {
|
251
|
-
|
308
|
+
boost::function<void ()> func = boost::bind(&AcceptLoadBalancer<Server>::mainLoop, this);
|
309
|
+
thread = new oxt::thread(boost::bind(runAndPrintExceptions, func, true),
|
252
310
|
"Load balancer");
|
253
311
|
}
|
254
312
|
|
@@ -632,6 +632,7 @@ protected:
|
|
632
632
|
|
633
633
|
virtual void reinitializeClient(Client *client, int fd) {
|
634
634
|
client->setConnState(Client::ACTIVE);
|
635
|
+
SKC_TRACE(client, 2, "Client associated with file descriptor: " << fd);
|
635
636
|
client->input.reinitialize(fd);
|
636
637
|
client->output.reinitialize(fd);
|
637
638
|
}
|
@@ -870,9 +871,10 @@ public:
|
|
870
871
|
disconnectedClientCount++;
|
871
872
|
|
872
873
|
deinitializeClient(c);
|
874
|
+
SKC_TRACE(c, 2, "Closing client file descriptor: " << fdnum);
|
873
875
|
try {
|
874
876
|
safelyClose(fdnum);
|
875
|
-
} catch (SystemException &e) {
|
877
|
+
} catch (const SystemException &e) {
|
876
878
|
SKC_WARN(c, "An error occurred while closing the client file descriptor: " <<
|
877
879
|
e.what() << " (errno=" << e.code() << ")");
|
878
880
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2010-
|
3
|
+
* Copyright (c) 2010-2015 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -110,6 +110,38 @@ splitIncludeSep(const StaticString &str, char sep, vector<StaticString> &output)
|
|
110
110
|
_splitIncludeSep(str, sep, output);
|
111
111
|
}
|
112
112
|
|
113
|
+
void
|
114
|
+
truncateBeforeTokens(const char* str, const char *tokens, int maxBetweenTokens, std::stringstream& sstream) {
|
115
|
+
std::string source(str);
|
116
|
+
|
117
|
+
if (source.empty()) {
|
118
|
+
return;
|
119
|
+
}
|
120
|
+
|
121
|
+
string::size_type copyStart, findStart, pos;
|
122
|
+
copyStart = 0; // for copying including the last found token
|
123
|
+
findStart = 0;
|
124
|
+
while ((pos = source.find_first_of(tokens, findStart)) != string::npos) {
|
125
|
+
// Determine & limit how many chars between two tokens (or start and first token)
|
126
|
+
int copyLen = pos - findStart;
|
127
|
+
if (copyLen > maxBetweenTokens) {
|
128
|
+
copyLen = maxBetweenTokens;
|
129
|
+
}
|
130
|
+
// Include token from the previous find (first iteration has no previous)
|
131
|
+
if (findStart > 0) {
|
132
|
+
copyLen++;
|
133
|
+
}
|
134
|
+
sstream << source.substr(copyStart, copyLen);
|
135
|
+
copyStart = pos;
|
136
|
+
findStart = pos + 1;
|
137
|
+
}
|
138
|
+
|
139
|
+
// Copy anything remaining (e.g. when no tokens at all)
|
140
|
+
if (copyStart < source.size()) {
|
141
|
+
sstream << source.substr(copyStart);
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
113
145
|
string
|
114
146
|
replaceString(const string &str, const string &toFind, const string &replaceWith) {
|
115
147
|
string::size_type pos = str.find(toFind);
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2010-
|
3
|
+
* Copyright (c) 2010-2015 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -128,6 +128,14 @@ void splitIncludeSep(const StaticString & restrict_ref str,
|
|
128
128
|
char sep,
|
129
129
|
vector<StaticString> & restrict_ref output);
|
130
130
|
|
131
|
+
/**
|
132
|
+
* Each section in str ending with any of the tokens is truncated to a length of maxBetweenTokens.
|
133
|
+
* The result is streamed to sstream, including tokens.
|
134
|
+
*
|
135
|
+
* Example: ("hello/world\\path/Splitter.cpp", "\\/", 3, sstream) results in sstream << "hel/wor\\pat/Splitter.cpp"
|
136
|
+
*/
|
137
|
+
void truncateBeforeTokens(const char* str, const char *tokens, int maxBetweenTokens, std::stringstream& sstream);
|
138
|
+
|
131
139
|
/**
|
132
140
|
* Look for 'toFind' inside 'str', replace it with 'replaceWith' and return the result.
|
133
141
|
* Only the first occurence of 'toFind' is replaced.
|
@@ -204,6 +204,7 @@ uintToString( LargestUInt value,
|
|
204
204
|
#include <iostream>
|
205
205
|
#include <stdexcept>
|
206
206
|
#include <string.h>
|
207
|
+
#include <boost/math/special_functions/fpclassify.hpp>
|
207
208
|
|
208
209
|
#if _MSC_VER >= 1400 // VC++ 8.0
|
209
210
|
#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
|
@@ -3459,6 +3460,10 @@ std::string valueToString( UInt value )
|
|
3459
3460
|
|
3460
3461
|
std::string valueToString( double value )
|
3461
3462
|
{
|
3463
|
+
if (!boost::math::isfinite(value)) {
|
3464
|
+
return "null";
|
3465
|
+
}
|
3466
|
+
|
3462
3467
|
char buffer[32];
|
3463
3468
|
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning.
|
3464
3469
|
sprintf_s(buffer, sizeof(buffer), "%#.16g", value);
|
@@ -715,9 +715,17 @@ constructHeaderBuffersForResponse(Request *req, struct iovec *buffers,
|
|
715
715
|
}
|
716
716
|
|
717
717
|
if (showVersionInHeader) {
|
718
|
-
|
718
|
+
#ifdef PASSENGER_IS_ENTERPRISE
|
719
|
+
PUSH_STATIC_BUFFER("X-Powered-By: " PROGRAM_NAME " Enterprise " PASSENGER_VERSION "\r\n\r\n");
|
720
|
+
#else
|
721
|
+
PUSH_STATIC_BUFFER("X-Powered-By: " PROGRAM_NAME " " PASSENGER_VERSION "\r\n\r\n");
|
722
|
+
#endif
|
719
723
|
} else {
|
720
|
-
|
724
|
+
#ifdef PASSENGER_IS_ENTERPRISE
|
725
|
+
PUSH_STATIC_BUFFER("X-Powered-By: " PROGRAM_NAME " Enterprise\r\n\r\n");
|
726
|
+
#else
|
727
|
+
PUSH_STATIC_BUFFER("X-Powered-By: " PROGRAM_NAME "\r\n\r\n");
|
728
|
+
#endif
|
721
729
|
}
|
722
730
|
|
723
731
|
nbuffers = i;
|
@@ -212,7 +212,11 @@ determineHeaderSizeForSessionProtocol(Request *req,
|
|
212
212
|
host->start->data + host->size - sep - 1);
|
213
213
|
} else {
|
214
214
|
state.serverName = StaticString(host->start->data, host->size);
|
215
|
-
|
215
|
+
if (req->https) {
|
216
|
+
state.serverPort = P_STATIC_STRING("443");
|
217
|
+
} else {
|
218
|
+
state.serverPort = P_STATIC_STRING("80");
|
219
|
+
}
|
216
220
|
}
|
217
221
|
} else {
|
218
222
|
state.serverName = defaultServerName;
|
@@ -162,12 +162,12 @@ private:
|
|
162
162
|
|
163
163
|
if (server->canKeepAlive(req)) {
|
164
164
|
if (httpVersion < 1010) {
|
165
|
-
// HTTP < 1.1 defaults to "Connection: close"
|
165
|
+
// HTTP < 1.1 defaults to "Connection: close", but we want keep-alive
|
166
166
|
PUSH_STATIC_STRING("Connection: keep-alive\r\n");
|
167
167
|
}
|
168
168
|
} else {
|
169
169
|
if (httpVersion >= 1010) {
|
170
|
-
// HTTP 1.1 defaults to "Connection: keep-alive"
|
170
|
+
// HTTP 1.1 defaults to "Connection: keep-alive", but we don't want it
|
171
171
|
PUSH_STATIC_STRING("Connection: close\r\n");
|
172
172
|
}
|
173
173
|
}
|
@@ -1215,6 +1215,8 @@ reportAgentsInformation(const WorkingObjectsPtr &wo, const vector<AgentWatcherPt
|
|
1215
1215
|
str = doc.toStyledString();
|
1216
1216
|
|
1217
1217
|
writeExact(wo->reportFile, str.data(), str.size());
|
1218
|
+
close(wo->reportFile);
|
1219
|
+
wo->reportFile = -1;
|
1218
1220
|
}
|
1219
1221
|
}
|
1220
1222
|
|
data/lib/phusion_passenger.rb
CHANGED
@@ -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 = '5.0.
|
33
|
+
VERSION_STRING = '5.0.3'
|
34
34
|
|
35
35
|
PREFERRED_NGINX_VERSION = '1.6.2'
|
36
36
|
NGINX_SHA256_CHECKSUM = 'b5608c2959d3e7ad09b20fc8f9e5bd4bc87b3bc8ba5936a513c04ed8f1391a18'
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Phusion Passenger - https://www.phusionpassenger.com/
|
2
|
-
# Copyright (c) 2010-
|
2
|
+
# Copyright (c) 2010-2015 Phusion
|
3
3
|
#
|
4
4
|
# "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
5
5
|
#
|
@@ -175,7 +175,12 @@ module PhusionPassenger
|
|
175
175
|
PhusionPassenger.require_passenger_lib 'platform_info/binary_compatibility'
|
176
176
|
puts PhusionPassenger::PlatformInfo.cxx_binary_compatibility_id
|
177
177
|
when "--version"
|
178
|
-
|
178
|
+
if defined?(PhusionPassenger::PASSENGER_IS_ENTERPRISE)
|
179
|
+
name = "#{PhusionPassenger::PROGRAM_NAME} Enterprise"
|
180
|
+
else
|
181
|
+
name = PhusionPassenger::PROGRAM_NAME
|
182
|
+
end
|
183
|
+
puts "#{name} #{PhusionPassenger::VERSION_STRING}"
|
179
184
|
when "--help"
|
180
185
|
self.class.help
|
181
186
|
else
|
@@ -84,6 +84,7 @@ module PhusionPassenger
|
|
84
84
|
begin
|
85
85
|
status, headers, body = @app.call(env)
|
86
86
|
rescue => e
|
87
|
+
disable_keep_alive
|
87
88
|
if should_reraise_app_error?(e, socket_wrapper)
|
88
89
|
raise e
|
89
90
|
elsif !should_swallow_app_error?(e, socket_wrapper)
|
@@ -101,6 +102,9 @@ module PhusionPassenger
|
|
101
102
|
|
102
103
|
begin
|
103
104
|
process_body(env, connection, socket_wrapper, status.to_i, headers, body)
|
105
|
+
rescue Exception => e
|
106
|
+
disable_keep_alive
|
107
|
+
raise
|
104
108
|
ensure
|
105
109
|
body.close if body && body.respond_to?(:close)
|
106
110
|
end
|
@@ -175,7 +179,6 @@ module PhusionPassenger
|
|
175
179
|
begin
|
176
180
|
if chunk
|
177
181
|
body.each do |part|
|
178
|
-
part = force_binary(part)
|
179
182
|
size = bytesize(part)
|
180
183
|
if size != 0
|
181
184
|
connection.writev(chunk_data(part, size))
|
@@ -188,6 +191,7 @@ module PhusionPassenger
|
|
188
191
|
end
|
189
192
|
end
|
190
193
|
rescue => e
|
194
|
+
disable_keep_alive
|
191
195
|
if should_reraise_app_error?(e, socket_wrapper)
|
192
196
|
raise e
|
193
197
|
elsif !should_swallow_app_error?(e, socket_wrapper)
|
@@ -232,6 +236,10 @@ module PhusionPassenger
|
|
232
236
|
end
|
233
237
|
end
|
234
238
|
|
239
|
+
def disable_keep_alive
|
240
|
+
@keepalive_performed = false
|
241
|
+
end
|
242
|
+
|
235
243
|
def should_output_body?(status, env)
|
236
244
|
return (status < 100 ||
|
237
245
|
(status >= 200 && status != 204 && status != 205 && status != 304)) &&
|
@@ -256,18 +264,6 @@ module PhusionPassenger
|
|
256
264
|
str.size
|
257
265
|
end
|
258
266
|
end
|
259
|
-
|
260
|
-
if "".respond_to?(:force_encoding)
|
261
|
-
BINARY = "binary".freeze
|
262
|
-
|
263
|
-
def force_binary(str)
|
264
|
-
str.force_encoding(BINARY)
|
265
|
-
end
|
266
|
-
else
|
267
|
-
def force_binary(str)
|
268
|
-
str
|
269
|
-
end
|
270
|
-
end
|
271
267
|
end
|
272
268
|
|
273
269
|
end # module Rack
|
@@ -68,10 +68,9 @@ module PhusionPassenger
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def build_daemon_controller_options
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
ping_spec = [:tcp, @options[:address], @options[:port]]
|
71
|
+
ping_spec = lambda do
|
72
|
+
File.exist?(report_file_path) &&
|
73
|
+
File.stat(report_file_path).size > 0
|
75
74
|
end
|
76
75
|
|
77
76
|
command = ""
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#include "TestSupport.h"
|
2
|
+
#include <Utils/StrIntUtils.h>
|
3
|
+
|
4
|
+
using namespace Passenger;
|
5
|
+
using namespace std;
|
6
|
+
|
7
|
+
namespace tut {
|
8
|
+
struct StrIntUtilsTest {
|
9
|
+
};
|
10
|
+
|
11
|
+
void testTruncate(const char* str, const char *tokens, int maxBetweenTokens, const char* expected) {
|
12
|
+
std::stringstream sstream;
|
13
|
+
truncateBeforeTokens(str, tokens, maxBetweenTokens, sstream);
|
14
|
+
ensure("got [" + sstream.str() + "], expected [" + expected + "]", sstream.str() == expected);
|
15
|
+
}
|
16
|
+
|
17
|
+
DEFINE_TEST_GROUP(StrIntUtilsTest);
|
18
|
+
|
19
|
+
TEST_METHOD(1) {
|
20
|
+
set_test_name("no change should occur");
|
21
|
+
testTruncate("", "", 0, "");
|
22
|
+
testTruncate("testwithout/tokens", "", 2, "testwithout/tokens");
|
23
|
+
testTruncate("", "/", 2, "");
|
24
|
+
testTruncate("/", "", 2, "/");
|
25
|
+
testTruncate("/", "/", 2, "/");
|
26
|
+
testTruncate("hello", "/", 2, "hello");
|
27
|
+
testTruncate("/hello", "/", 3, "/hello");
|
28
|
+
} TEST_METHOD(2) {
|
29
|
+
set_test_name("truncation must not touch begin/end token");
|
30
|
+
testTruncate("hello/", "/", 3, "hel/");
|
31
|
+
testTruncate("/hello/", "/", 3, "/hel/");
|
32
|
+
} TEST_METHOD(3) {
|
33
|
+
set_test_name("exact truncation and multiple split tokens");
|
34
|
+
testTruncate("hello/world/Main.cpp", "/", 2, "he/wo/Main.cpp");
|
35
|
+
testTruncate("hello/world\\Main.cpp", "/\\", 1, "h/w\\Main.cpp");
|
36
|
+
testTruncate("hello/world\\Main.cpp", "/", 1, "h/world\\Main.cpp");
|
37
|
+
testTruncate("/he/llo/worl/", "/", 3, "/he/llo/wor/");
|
38
|
+
}
|
39
|
+
}
|
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: 5.0.
|
4
|
+
version: 5.0.3
|
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: 2015-03-
|
11
|
+
date: 2015-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -3009,6 +3009,7 @@ files:
|
|
3009
3009
|
- test/cxx/TestSupport.cpp
|
3010
3010
|
- test/cxx/TestSupport.h
|
3011
3011
|
- test/cxx/UnionStationTest.cpp
|
3012
|
+
- test/cxx/Utils/StrIntUtilsTest.cpp
|
3012
3013
|
- test/cxx/UtilsTest.cpp
|
3013
3014
|
- test/cxx/VariantMapTest.cpp
|
3014
3015
|
- test/gdbinit.example
|
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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
=
|
5
|
+
iQEcBAABAgAGBQJVAMF1AAoJECrHRaUKISqMImsIAJTQzyvYQ8pEqJsRuCK2E4aI
|
6
|
+
cJCVHsWzz4M1rYG9ICtenTynE8Xahdf1n74sGjmd4cXY67V1b6EUXutOUH1JIa4n
|
7
|
+
R/rDSvqvK/Fuj3B8r1Or87HwFqLdMEjCUd08GCGXtERAeswgaoQqXfM05x2V8cdp
|
8
|
+
7UJdo2w0uPjEauDl0AD8lWNEWInTLw61uXkNkjfG04kMDmcgi8ZxK9epBmBjeX88
|
9
|
+
byVAoKxOj0vXUCN9LDsJ4p1cQ+URqQPJUS88jBKNSi2S+S7V29CzauSHa/7yLnFK
|
10
|
+
JOA55NXHpFfV9XCmeQHvq52bIBp1qfW5Umif0Gjv9v11P0bl3k9neJ1psLKRCZ8=
|
11
|
+
=Ycnq
|
12
12
|
-----END PGP SIGNATURE-----
|