passenger 4.0.48 → 4.0.49
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/.editorconfig +36 -2
- data/.travis.yml +1 -1
- data/CHANGELOG +16 -0
- data/Rakefile +0 -1
- data/build/apache2.rb +4 -4
- data/build/common_library.rb +18 -18
- data/build/cplusplus_support.rb +2 -2
- data/build/documentation.rb +1 -1
- data/build/integration_tests.rb +12 -4
- data/build/misc.rb +12 -7
- data/build/packaging.rb +14 -14
- data/build/preprocessor.rb +10 -10
- data/build/rake_extensions.rb +11 -11
- data/build/ruby_extension.rb +2 -2
- data/dev/ci/inituidgid +24 -0
- data/dev/ci/run_jenkins.sh +57 -0
- data/dev/ci/run_rpm_tests.sh +77 -0
- data/dev/{run_travis.sh → ci/run_travis.sh} +60 -4
- data/doc/Users guide Nginx.txt +2 -2
- data/doc/users_guide_snippets/environment_variables.txt +0 -2
- data/doc/users_guide_snippets/tips.txt +20 -1
- data/ext/apache2/Bucket.cpp +18 -18
- data/ext/apache2/Bucket.h +4 -4
- data/ext/apache2/Configuration.cpp +7 -7
- data/ext/apache2/Configuration.hpp +43 -43
- data/ext/apache2/DirectoryMapper.h +5 -5
- data/ext/apache2/Hooks.cpp +142 -142
- data/ext/apache2/MergeDirConfig.cpp +40 -40
- data/ext/common/Account.h +17 -17
- data/ext/common/AccountsDatabase.h +9 -9
- data/ext/common/AgentsStarter.cpp +2 -2
- data/ext/common/AgentsStarter.h +40 -40
- data/ext/common/ApplicationPool2/Common.h +10 -6
- data/ext/common/ApplicationPool2/ComponentInfo.h +2 -2
- data/ext/common/ApplicationPool2/DirectSpawner.h +17 -17
- data/ext/common/ApplicationPool2/DummySpawner.h +5 -5
- data/ext/common/ApplicationPool2/Group.h +54 -38
- data/ext/common/ApplicationPool2/Implementation.cpp +76 -49
- data/ext/common/ApplicationPool2/Options.h +98 -91
- data/ext/common/ApplicationPool2/Pool.h +70 -69
- data/ext/common/ApplicationPool2/Process.h +21 -21
- data/ext/common/ApplicationPool2/Session.h +11 -11
- data/ext/common/ApplicationPool2/SmartSpawner.h +60 -60
- data/ext/common/ApplicationPool2/Socket.h +19 -19
- data/ext/common/ApplicationPool2/Spawner.h +64 -72
- data/ext/common/ApplicationPool2/SpawnerFactory.h +4 -4
- data/ext/common/ApplicationPool2/SuperGroup.h +41 -41
- data/ext/common/BackgroundEventLoop.cpp +1 -1
- data/ext/common/BackgroundEventLoop.h +2 -2
- data/ext/common/Constants.h +1 -1
- data/ext/common/EventedBufferedInput.h +5 -5
- data/ext/common/EventedClient.h +51 -51
- data/ext/common/EventedMessageServer.h +39 -39
- data/ext/common/EventedServer.h +32 -32
- data/ext/common/Exceptions.h +23 -23
- data/ext/common/FileDescriptor.h +18 -18
- data/ext/common/Logging.cpp +1 -1
- data/ext/common/MessageClient.h +27 -27
- data/ext/common/MessageReadersWriters.h +79 -79
- data/ext/common/MessageServer.h +59 -59
- data/ext/common/RandomGenerator.h +12 -12
- data/ext/common/ResourceLocator.h +8 -8
- data/ext/common/SafeLibev.h +54 -25
- data/ext/common/ServerInstanceDir.h +31 -31
- data/ext/common/StaticString.h +50 -48
- data/ext/common/Utils.cpp +73 -78
- data/ext/common/Utils.h +6 -6
- data/ext/common/Utils/Base64.cpp +3 -3
- data/ext/common/Utils/Base64.h +7 -7
- data/ext/common/Utils/BlockingQueue.h +9 -9
- data/ext/common/Utils/BufferedIO.h +17 -17
- data/ext/common/Utils/CachedFileStat.hpp +16 -16
- data/ext/common/Utils/Dechunker.h +25 -25
- data/ext/common/Utils/FileChangeChecker.h +10 -10
- data/ext/common/Utils/MemZeroGuard.h +5 -5
- data/ext/common/Utils/MemoryBarrier.h +1 -1
- data/ext/common/Utils/MessageIO.h +61 -61
- data/ext/common/Utils/ProcessMetricsCollector.h +40 -40
- data/ext/common/Utils/ScopeGuard.h +7 -7
- data/ext/common/Utils/SpeedMeter.h +1 -1
- data/ext/common/Utils/StrIntUtils.cpp +13 -13
- data/ext/common/Utils/StrIntUtils.h +3 -3
- data/ext/common/Utils/StringScanning.h +5 -5
- data/ext/common/Utils/SystemMetricsCollector.h +2 -2
- data/ext/common/Utils/SystemTime.h +10 -10
- data/ext/common/Utils/Template.h +2 -2
- data/ext/common/Utils/Timer.h +6 -6
- data/ext/common/Utils/VariantMap.h +29 -29
- data/ext/common/agents/Base.cpp +19 -19
- data/ext/common/agents/HelperAgent/AgentOptions.h +1 -1
- data/ext/common/agents/HelperAgent/FileBackedPipe.h +6 -6
- data/ext/common/agents/HelperAgent/Main.cpp +44 -43
- data/ext/common/agents/HelperAgent/RequestHandler.cpp +4 -4
- data/ext/common/agents/HelperAgent/RequestHandler.h +29 -28
- data/ext/common/agents/HelperAgent/ScgiRequestParser.h +56 -50
- data/ext/common/agents/LoggingAgent/AdminController.h +8 -8
- data/ext/common/agents/LoggingAgent/DataStoreId.h +17 -17
- data/ext/common/agents/LoggingAgent/FilterSupport.h +167 -167
- data/ext/common/agents/LoggingAgent/LoggingServer.h +122 -122
- data/ext/common/agents/LoggingAgent/Main.cpp +7 -7
- data/ext/common/agents/LoggingAgent/RemoteSender.h +54 -54
- data/ext/common/agents/SpawnPreparer.cpp +4 -4
- data/ext/common/agents/TempDirToucher.c +2 -2
- data/ext/common/agents/Watchdog/AgentWatcher.cpp +47 -47
- data/ext/common/agents/Watchdog/HelperAgentWatcher.cpp +7 -7
- data/ext/common/agents/Watchdog/LoggingAgentWatcher.cpp +7 -7
- data/ext/common/agents/Watchdog/Main.cpp +22 -22
- data/ext/common/agents/Watchdog/ServerInstanceDirToucher.cpp +9 -9
- data/ext/libeio/eio.c +1 -1
- data/ext/nginx/Configuration.c +30 -30
- data/ext/nginx/Configuration.h +1 -1
- data/ext/nginx/ContentHandler.c +54 -54
- data/ext/nginx/ContentHandler.h +3 -3
- data/ext/nginx/StaticContentHandler.c +2 -2
- data/ext/nginx/ngx_http_passenger_module.c +21 -21
- data/ext/oxt/detail/backtrace_enabled.hpp +1 -1
- data/ext/oxt/detail/context.hpp +1 -1
- data/ext/oxt/detail/spin_lock_darwin.hpp +4 -4
- data/ext/oxt/detail/spin_lock_gcc_x86.hpp +3 -3
- data/ext/oxt/detail/spin_lock_pthreads.hpp +4 -4
- data/ext/oxt/detail/tracable_exception_disabled.hpp +1 -1
- data/ext/oxt/dynamic_thread_group.hpp +18 -18
- data/ext/oxt/implementation.cpp +9 -8
- data/ext/oxt/macros.hpp +2 -2
- data/ext/oxt/system_calls.cpp +11 -11
- data/ext/oxt/system_calls.hpp +13 -13
- data/ext/oxt/thread.hpp +22 -14
- data/ext/ruby/passenger_native_support.c +55 -55
- data/lib/phusion_passenger.rb +24 -24
- data/lib/phusion_passenger/common_library.rb +2 -0
- data/lib/phusion_passenger/loader_shared_helpers.rb +18 -18
- data/lib/phusion_passenger/packaging.rb +9 -4
- data/lib/phusion_passenger/platform_info/apache.rb +45 -31
- data/lib/phusion_passenger/platform_info/compiler.rb +11 -11
- data/lib/phusion_passenger/rack/thread_handler_extension.rb +1 -1
- data/lib/phusion_passenger/request_handler/thread_handler.rb +8 -8
- data/lib/phusion_passenger/standalone/app_finder.rb +16 -16
- data/lib/phusion_passenger/standalone/command.rb +22 -22
- data/packaging/rpm/LICENSE.txt +19 -0
- data/packaging/rpm/Makefile +13 -0
- data/packaging/rpm/README.md +41 -0
- data/packaging/rpm/Vagrantfile +38 -0
- data/{rpm/Vagrantfile → packaging/rpm/Vagrantfile.centos} +0 -0
- data/packaging/rpm/build +170 -0
- data/packaging/rpm/create_project +41 -0
- data/packaging/rpm/git_update +88 -0
- data/packaging/rpm/image/Dockerfile +37 -0
- data/packaging/rpm/image/Gemfile +3 -0
- data/packaging/rpm/image/Gemfile.lock +12 -0
- data/packaging/rpm/image/RPM-GPG-KEY-amazon-ga +19 -0
- data/packaging/rpm/image/amazon2014-i386.cfg +96 -0
- data/packaging/rpm/image/amazon2014-x86_64.cfg +96 -0
- data/packaging/rpm/image/site-defaults.cfg +168 -0
- data/packaging/rpm/internal/build_tasks.rb +238 -0
- data/packaging/rpm/internal/dummygpg +11 -0
- data/packaging/rpm/internal/exec_build +42 -0
- data/packaging/rpm/internal/get_distro_arch +14 -0
- data/packaging/rpm/internal/get_distro_id +10 -0
- data/packaging/rpm/internal/git_update +27 -0
- data/packaging/rpm/internal/inituidgid +17 -0
- data/packaging/rpm/internal/my_init +344 -0
- data/packaging/rpm/internal/python27 +3 -0
- data/packaging/rpm/internal/repo_update +46 -0
- data/packaging/rpm/internal/setuser +26 -0
- data/packaging/rpm/internal/tracking_helper +40 -0
- data/packaging/rpm/jenkins_release +99 -0
- data/packaging/rpm/lib/build_tasks_support.rb +402 -0
- data/packaging/rpm/lib/preprocessor.rb +341 -0
- data/packaging/rpm/nginx_spec/404.html +119 -0
- data/packaging/rpm/nginx_spec/50x.html +119 -0
- data/packaging/rpm/nginx_spec/index.html +116 -0
- data/packaging/rpm/nginx_spec/nginx-auto-cc-gcc.patch +13 -0
- data/packaging/rpm/nginx_spec/nginx-logo.png +0 -0
- data/packaging/rpm/nginx_spec/nginx-upgrade +13 -0
- data/packaging/rpm/nginx_spec/nginx-upgrade.8 +151 -0
- data/packaging/rpm/nginx_spec/nginx.conf +131 -0
- data/packaging/rpm/nginx_spec/nginx.init +144 -0
- data/packaging/rpm/nginx_spec/nginx.logrotate +13 -0
- data/packaging/rpm/nginx_spec/nginx.service +15 -0
- data/packaging/rpm/nginx_spec/nginx.spec.template +559 -0
- data/packaging/rpm/nginx_spec/nginx.sysconfig +4 -0
- data/packaging/rpm/nginx_spec/passenger.conf +9 -0
- data/packaging/rpm/nginx_spec/poweredby.png +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/apache-passenger.conf.in +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/config.json +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/passenger.logrotate +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/passenger.spec.template +58 -31
- data/{rpm → packaging/rpm/passenger_spec}/passenger_dynamic_thread_group.patch +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/passenger_tests_default_config_example.patch +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/rubygem-passenger-4.0.18-GLIBC_HAVE_LONG_LONG.patch +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/rubygem-passenger-4.0.18-gcc47-include-sys_types.patch +0 -0
- data/packaging/rpm/repo_update +114 -0
- data/packaging/rpm/setup-system +60 -0
- data/packaging/rpm/shell +10 -0
- data/resources/templates/standalone/config.erb +3 -1
- data/test/config.json.rpm-automation +1 -1
- data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +11 -11
- data/test/cxx/ApplicationPool2/OptionsTest.cpp +5 -5
- data/test/cxx/ApplicationPool2/PoolTest.cpp +129 -89
- data/test/cxx/ApplicationPool2/ProcessTest.cpp +15 -15
- data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +22 -22
- data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +11 -11
- data/test/cxx/ScgiRequestParserTest.cpp +75 -61
- data/test/cxx/UtilsTest.cpp +86 -85
- data/test/gdbinit.example +3 -0
- data/test/integration_tests/nginx_tests.rb +3 -3
- data/test/integration_tests/source_packaging_test.rb +3 -1
- data/test/stub/nginx/nginx.conf.erb +8 -1
- data/test/support/nginx_controller.rb +7 -7
- metadata +62 -17
- metadata.gz.asc +7 -7
- data/build/rpm.rb +0 -128
- data/dev/rpmtool +0 -21
- data/dev/test_rpm_packaging.sh +0 -28
- data/rpm/get_distro_id.py +0 -4
@@ -49,13 +49,13 @@ struct Connection {
|
|
49
49
|
int fd;
|
50
50
|
bool persistent: 1;
|
51
51
|
bool fail: 1;
|
52
|
-
|
52
|
+
|
53
53
|
Connection() {
|
54
54
|
fd = -1;
|
55
55
|
persistent = false;
|
56
56
|
fail = false;
|
57
57
|
}
|
58
|
-
|
58
|
+
|
59
59
|
void close() {
|
60
60
|
if (fd != -1) {
|
61
61
|
int fd2 = fd;
|
@@ -75,37 +75,37 @@ private:
|
|
75
75
|
boost::mutex connectionPoolLock;
|
76
76
|
int totalConnections;
|
77
77
|
vector<Connection> idleConnections;
|
78
|
-
|
78
|
+
|
79
79
|
int connectionPoolLimit() const {
|
80
80
|
return concurrency;
|
81
81
|
}
|
82
|
-
|
82
|
+
|
83
83
|
Connection connect() const {
|
84
84
|
Connection connection;
|
85
85
|
P_TRACE(3, "Connecting to " << address);
|
86
86
|
connection.fd = connectToServer(address);
|
87
87
|
return connection;
|
88
88
|
}
|
89
|
-
|
89
|
+
|
90
90
|
public:
|
91
91
|
// Read-only.
|
92
92
|
string name;
|
93
93
|
string address;
|
94
94
|
string protocol;
|
95
95
|
int concurrency;
|
96
|
-
|
96
|
+
|
97
97
|
/** The handle inside the associated Process's 'sessionSockets' priority queue.
|
98
98
|
* Guaranteed to be valid as long as the Process is alive.
|
99
99
|
*/
|
100
100
|
PriorityQueue<Socket>::Handle pqHandle;
|
101
|
-
|
101
|
+
|
102
102
|
/** Invariant: sessions >= 0 */
|
103
103
|
int sessions;
|
104
|
-
|
104
|
+
|
105
105
|
Socket()
|
106
106
|
: concurrency(0)
|
107
107
|
{ }
|
108
|
-
|
108
|
+
|
109
109
|
Socket(const string &_name, const string &_address, const string &_protocol, int _concurrency)
|
110
110
|
: totalConnections(0),
|
111
111
|
name(_name),
|
@@ -114,7 +114,7 @@ public:
|
|
114
114
|
concurrency(_concurrency),
|
115
115
|
sessions(0)
|
116
116
|
{ }
|
117
|
-
|
117
|
+
|
118
118
|
Socket(const Socket &other)
|
119
119
|
: totalConnections(other.totalConnections),
|
120
120
|
idleConnections(other.idleConnections),
|
@@ -125,7 +125,7 @@ public:
|
|
125
125
|
pqHandle(other.pqHandle),
|
126
126
|
sessions(other.sessions)
|
127
127
|
{ }
|
128
|
-
|
128
|
+
|
129
129
|
Socket &operator=(const Socket &other) {
|
130
130
|
totalConnections = other.totalConnections;
|
131
131
|
idleConnections = other.idleConnections;
|
@@ -137,7 +137,7 @@ public:
|
|
137
137
|
sessions = other.sessions;
|
138
138
|
return *this;
|
139
139
|
}
|
140
|
-
|
140
|
+
|
141
141
|
/**
|
142
142
|
* Connect to this socket or reuse an existing connection.
|
143
143
|
*
|
@@ -146,7 +146,7 @@ public:
|
|
146
146
|
*/
|
147
147
|
Connection checkoutConnection() {
|
148
148
|
boost::lock_guard<boost::mutex> l(connectionPoolLock);
|
149
|
-
|
149
|
+
|
150
150
|
if (!idleConnections.empty()) {
|
151
151
|
Connection connection = idleConnections.back();
|
152
152
|
idleConnections.pop_back();
|
@@ -160,10 +160,10 @@ public:
|
|
160
160
|
return connect();
|
161
161
|
}
|
162
162
|
}
|
163
|
-
|
163
|
+
|
164
164
|
void checkinConnection(Connection connection) {
|
165
165
|
boost::unique_lock<boost::mutex> l(connectionPoolLock);
|
166
|
-
|
166
|
+
|
167
167
|
if (connection.persistent) {
|
168
168
|
if (connection.fail) {
|
169
169
|
totalConnections--;
|
@@ -177,12 +177,12 @@ public:
|
|
177
177
|
connection.close();
|
178
178
|
}
|
179
179
|
}
|
180
|
-
|
181
|
-
|
180
|
+
|
181
|
+
|
182
182
|
bool isIdle() const {
|
183
183
|
return sessions == 0;
|
184
184
|
}
|
185
|
-
|
185
|
+
|
186
186
|
int busyness() const {
|
187
187
|
/* Different sockets within a Process may have different
|
188
188
|
* 'concurrency' values. We want:
|
@@ -204,7 +204,7 @@ public:
|
|
204
204
|
return (int) (((long long) sessions * INT_MAX) / (double) concurrency);
|
205
205
|
}
|
206
206
|
}
|
207
|
-
|
207
|
+
|
208
208
|
bool isTotallyBusy() const {
|
209
209
|
return concurrency != 0 && sessions >= concurrency;
|
210
210
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2011-
|
3
|
+
* Copyright (c) 2011-2014 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -57,6 +57,7 @@
|
|
57
57
|
#include <map>
|
58
58
|
#include <vector>
|
59
59
|
#include <utility>
|
60
|
+
#include <algorithm>
|
60
61
|
#include <boost/make_shared.hpp>
|
61
62
|
#include <boost/shared_array.hpp>
|
62
63
|
#include <boost/bind.hpp>
|
@@ -107,7 +108,7 @@ class Spawner {
|
|
107
108
|
protected:
|
108
109
|
friend struct tut::ApplicationPool2_DirectSpawnerTest;
|
109
110
|
friend struct tut::ApplicationPool2_SmartSpawnerTest;
|
110
|
-
|
111
|
+
|
111
112
|
/**
|
112
113
|
* Given a file descriptor, captures its output in a background thread
|
113
114
|
* and also forwards it immediately to a target file descriptor.
|
@@ -122,13 +123,13 @@ protected:
|
|
122
123
|
boost::mutex dataSyncher;
|
123
124
|
string data;
|
124
125
|
oxt::thread *thr;
|
125
|
-
|
126
|
+
|
126
127
|
void capture() {
|
127
128
|
TRACE_POINT();
|
128
129
|
while (!this_thread::interruption_requested()) {
|
129
130
|
char buf[1024 * 8];
|
130
131
|
ssize_t ret;
|
131
|
-
|
132
|
+
|
132
133
|
UPDATE_TRACE_POINT();
|
133
134
|
ret = syscalls::read(fd, buf, sizeof(buf));
|
134
135
|
int e = errno;
|
@@ -162,7 +163,7 @@ protected:
|
|
162
163
|
}
|
163
164
|
}
|
164
165
|
}
|
165
|
-
|
166
|
+
|
166
167
|
public:
|
167
168
|
BackgroundIOCapturer(const FileDescriptor &_fd, pid_t _pid, const char *_channelName)
|
168
169
|
: fd(_fd),
|
@@ -170,7 +171,7 @@ protected:
|
|
170
171
|
channelName(_channelName),
|
171
172
|
thr(NULL)
|
172
173
|
{ }
|
173
|
-
|
174
|
+
|
174
175
|
~BackgroundIOCapturer() {
|
175
176
|
TRACE_POINT();
|
176
177
|
if (thr != NULL) {
|
@@ -181,17 +182,17 @@ protected:
|
|
181
182
|
thr = NULL;
|
182
183
|
}
|
183
184
|
}
|
184
|
-
|
185
|
+
|
185
186
|
const FileDescriptor &getFd() const {
|
186
187
|
return fd;
|
187
188
|
}
|
188
|
-
|
189
|
+
|
189
190
|
void start() {
|
190
191
|
assert(thr == NULL);
|
191
192
|
thr = new oxt::thread(boost::bind(&BackgroundIOCapturer::capture, this),
|
192
193
|
"Background I/O capturer", 64 * 1024);
|
193
194
|
}
|
194
|
-
|
195
|
+
|
195
196
|
string stop() {
|
196
197
|
TRACE_POINT();
|
197
198
|
assert(thr != NULL);
|
@@ -210,9 +211,9 @@ protected:
|
|
210
211
|
data.append(dataToAdd.data(), dataToAdd.size());
|
211
212
|
}
|
212
213
|
};
|
213
|
-
|
214
|
+
|
214
215
|
typedef boost::shared_ptr<BackgroundIOCapturer> BackgroundIOCapturerPtr;
|
215
|
-
|
216
|
+
|
216
217
|
/**
|
217
218
|
* A temporary directory for spawned child processes to write
|
218
219
|
* debugging information to. It is removed after spawning has
|
@@ -345,14 +346,14 @@ protected:
|
|
345
346
|
FileDescriptor errorPipe;
|
346
347
|
const Options *options;
|
347
348
|
DebugDirPtr debugDir;
|
348
|
-
|
349
|
+
|
349
350
|
/****** Working state ******/
|
350
351
|
BufferedIO io;
|
351
352
|
string gupid;
|
352
353
|
string connectPassword;
|
353
354
|
unsigned long long spawnStartTime;
|
354
355
|
unsigned long long timeout;
|
355
|
-
|
356
|
+
|
356
357
|
NegotiationDetails() {
|
357
358
|
preparation = NULL;
|
358
359
|
pid = 0;
|
@@ -361,8 +362,8 @@ protected:
|
|
361
362
|
timeout = 0;
|
362
363
|
}
|
363
364
|
};
|
364
|
-
|
365
|
-
|
365
|
+
|
366
|
+
|
366
367
|
private:
|
367
368
|
/**
|
368
369
|
* Appends key + "\0" + value + "\0" to 'output'.
|
@@ -425,7 +426,7 @@ private:
|
|
425
426
|
SocketListPtr sockets = boost::make_shared<SocketList>();
|
426
427
|
while (true) {
|
427
428
|
string line;
|
428
|
-
|
429
|
+
|
429
430
|
try {
|
430
431
|
line = readMessageLine(details);
|
431
432
|
} catch (const SystemException &e) {
|
@@ -440,7 +441,7 @@ private:
|
|
440
441
|
SpawnException::APP_STARTUP_TIMEOUT,
|
441
442
|
details);
|
442
443
|
}
|
443
|
-
|
444
|
+
|
444
445
|
if (line.empty()) {
|
445
446
|
throwAppSpawnException("An error occurred while starting the "
|
446
447
|
"web application. It unexpected closed the connection while "
|
@@ -456,7 +457,7 @@ private:
|
|
456
457
|
} else if (line == "\n") {
|
457
458
|
break;
|
458
459
|
}
|
459
|
-
|
460
|
+
|
460
461
|
string::size_type pos = line.find(": ");
|
461
462
|
if (pos == string::npos) {
|
462
463
|
throwAppSpawnException("An error occurred while starting the "
|
@@ -465,7 +466,7 @@ private:
|
|
465
466
|
SpawnException::APP_STARTUP_PROTOCOL_ERROR,
|
466
467
|
details);
|
467
468
|
}
|
468
|
-
|
469
|
+
|
469
470
|
string key = line.substr(0, pos);
|
470
471
|
string value = line.substr(pos + 2, line.size() - pos - 3);
|
471
472
|
if (key == "socket") {
|
@@ -525,7 +526,7 @@ private:
|
|
525
526
|
SpawnException::APP_STARTUP_PROTOCOL_ERROR,
|
526
527
|
details);
|
527
528
|
}
|
528
|
-
|
529
|
+
|
529
530
|
ProcessPtr process = boost::make_shared<Process>(
|
530
531
|
details.pid,
|
531
532
|
details.gupid, details.connectPassword,
|
@@ -534,17 +535,17 @@ private:
|
|
534
535
|
process->codeRevision = details.preparation->codeRevision;
|
535
536
|
return process;
|
536
537
|
}
|
537
|
-
|
538
|
+
|
538
539
|
protected:
|
539
540
|
ServerInstanceDir::GenerationPtr generation;
|
540
541
|
SpawnerConfigPtr config;
|
541
|
-
|
542
|
+
|
542
543
|
static void nonInterruptableKillAndWaitpid(pid_t pid) {
|
543
544
|
this_thread::disable_syscall_interruption dsi;
|
544
545
|
syscalls::kill(pid, SIGKILL);
|
545
546
|
syscalls::waitpid(pid, NULL, 0);
|
546
547
|
}
|
547
|
-
|
548
|
+
|
548
549
|
/**
|
549
550
|
* Behaves like <tt>waitpid(pid, status, WNOHANG)</tt>, but waits at most
|
550
551
|
* <em>timeout</em> miliseconds for the process to exit.
|
@@ -552,7 +553,7 @@ protected:
|
|
552
553
|
static int timedWaitpid(pid_t pid, int *status, unsigned long long timeout) {
|
553
554
|
Timer timer;
|
554
555
|
int ret;
|
555
|
-
|
556
|
+
|
556
557
|
do {
|
557
558
|
ret = syscalls::waitpid(pid, status, WNOHANG);
|
558
559
|
if (ret > 0 || ret == -1) {
|
@@ -563,7 +564,7 @@ protected:
|
|
563
564
|
} while (timer.elapsed() < timeout);
|
564
565
|
return 0; // timed out
|
565
566
|
}
|
566
|
-
|
567
|
+
|
567
568
|
static string fixupSocketAddress(const Options &options, const string &address) {
|
568
569
|
TRACE_POINT();
|
569
570
|
if (!options.preexecChroot.empty() && !options.postexecChroot.empty()) {
|
@@ -662,7 +663,7 @@ protected:
|
|
662
663
|
// and whether postexecChroot is a child directory of appRoot.
|
663
664
|
}
|
664
665
|
}
|
665
|
-
|
666
|
+
|
666
667
|
static void createCommandArgs(const vector<string> &command,
|
667
668
|
shared_array<const char *> &args)
|
668
669
|
{
|
@@ -678,7 +679,7 @@ protected:
|
|
678
679
|
throw RuntimeException("An internal error!");
|
679
680
|
}
|
680
681
|
}
|
681
|
-
|
682
|
+
|
682
683
|
void throwAppSpawnException(const string &msg,
|
683
684
|
SpawnException::ErrorKind errorKind,
|
684
685
|
NegotiationDetails &details)
|
@@ -690,7 +691,7 @@ protected:
|
|
690
691
|
if (details.stderrCapturer != NULL) {
|
691
692
|
stderrOutput = details.stderrCapturer->stop();
|
692
693
|
}
|
693
|
-
|
694
|
+
|
694
695
|
// If the exception wasn't due to a timeout, try to capture the
|
695
696
|
// remaining stderr output for at most 2 seconds.
|
696
697
|
if (errorKind != SpawnException::PRELOADER_STARTUP_TIMEOUT
|
@@ -702,7 +703,7 @@ protected:
|
|
702
703
|
while (!done) {
|
703
704
|
char buf[1024 * 32];
|
704
705
|
unsigned int ret;
|
705
|
-
|
706
|
+
|
706
707
|
try {
|
707
708
|
ret = readExact(details.stderrCapturer->getFd(), buf,
|
708
709
|
sizeof(buf), &timeout);
|
@@ -720,7 +721,7 @@ protected:
|
|
720
721
|
}
|
721
722
|
}
|
722
723
|
details.stderrCapturer.reset();
|
723
|
-
|
724
|
+
|
724
725
|
// Now throw SpawnException with the captured stderr output
|
725
726
|
// as error response.
|
726
727
|
SpawnException e(msg,
|
@@ -782,7 +783,7 @@ protected:
|
|
782
783
|
if (!line.empty() && line[line.size() - 1] == '\n') {
|
783
784
|
line.erase(line.size() - 1, 1);
|
784
785
|
}
|
785
|
-
|
786
|
+
|
786
787
|
if (result.empty()) {
|
787
788
|
// EOF
|
788
789
|
return result;
|
@@ -840,11 +841,9 @@ protected:
|
|
840
841
|
long bufSize;
|
841
842
|
shared_array<char> strings;
|
842
843
|
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
bufSize = 1024 * 64;
|
847
|
-
}
|
844
|
+
// _SC_GETPW_R_SIZE_MAX is not a maximum:
|
845
|
+
// http://tomlee.co/2012/10/problems-with-large-linux-unix-groups-and-getgrgid_r-getgrnam_r/
|
846
|
+
bufSize = std::max<long>(1024 * 128, sysconf(_SC_GETPW_R_SIZE_MAX));
|
848
847
|
strings.reset(new char[bufSize]);
|
849
848
|
|
850
849
|
userInfo = (struct passwd *) NULL;
|
@@ -855,7 +854,7 @@ protected:
|
|
855
854
|
getProcessUsername() + "; it looks like your system's " +
|
856
855
|
"user database is broken, please fix it.");
|
857
856
|
}
|
858
|
-
|
857
|
+
|
859
858
|
info.switchUser = false;
|
860
859
|
info.username = userInfo->pw_name;
|
861
860
|
info.groupname = getGroupName(userInfo->pw_gid);
|
@@ -866,7 +865,7 @@ protected:
|
|
866
865
|
info.ngroups = 0;
|
867
866
|
return;
|
868
867
|
}
|
869
|
-
|
868
|
+
|
870
869
|
UPDATE_TRACE_POINT();
|
871
870
|
string defaultGroup;
|
872
871
|
string startupFile = absolutizePath(options.getStartupFile(), info.appRoot);
|
@@ -876,19 +875,12 @@ protected:
|
|
876
875
|
long pwdBufSize, grpBufSize;
|
877
876
|
shared_array<char> pwdBuf, grpBuf;
|
878
877
|
int ret;
|
879
|
-
|
880
|
-
pwdBufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
|
881
|
-
if (pwdBufSize == -1) {
|
882
|
-
// Let's hope this is enough.
|
883
|
-
pwdBufSize = 1024 * 64;
|
884
|
-
}
|
885
|
-
pwdBuf.reset(new char[pwdBufSize]);
|
886
878
|
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
879
|
+
// _SC_GETPW_R_SIZE_MAX/_SC_GETGR_R_SIZE_MAX are not maximums:
|
880
|
+
// http://tomlee.co/2012/10/problems-with-large-linux-unix-groups-and-getgrgid_r-getgrnam_r/
|
881
|
+
pwdBufSize = std::max<long>(1024 * 128, sysconf(_SC_GETPW_R_SIZE_MAX));
|
882
|
+
pwdBuf.reset(new char[pwdBufSize]);
|
883
|
+
grpBufSize = std::max<long>(1024 * 128, sysconf(_SC_GETGR_R_SIZE_MAX));
|
892
884
|
grpBuf.reset(new char[grpBufSize]);
|
893
885
|
|
894
886
|
if (options.defaultGroup.empty()) {
|
@@ -920,7 +912,7 @@ protected:
|
|
920
912
|
} else {
|
921
913
|
defaultGroup = options.defaultGroup;
|
922
914
|
}
|
923
|
-
|
915
|
+
|
924
916
|
UPDATE_TRACE_POINT();
|
925
917
|
userInfo = (struct passwd *) NULL;
|
926
918
|
if (!options.user.empty()) {
|
@@ -950,7 +942,7 @@ protected:
|
|
950
942
|
userInfo = (struct passwd *) NULL;
|
951
943
|
}
|
952
944
|
}
|
953
|
-
|
945
|
+
|
954
946
|
UPDATE_TRACE_POINT();
|
955
947
|
if (!options.group.empty()) {
|
956
948
|
struct group *groupInfo = (struct group *) NULL;
|
@@ -1000,7 +992,7 @@ protected:
|
|
1000
992
|
if (groupId == (gid_t) -1) {
|
1001
993
|
throw RuntimeException("Cannot determine a group to lower privilege to");
|
1002
994
|
}
|
1003
|
-
|
995
|
+
|
1004
996
|
UPDATE_TRACE_POINT();
|
1005
997
|
#ifdef __APPLE__
|
1006
998
|
int groups[1024];
|
@@ -1110,11 +1102,11 @@ protected:
|
|
1110
1102
|
return false;
|
1111
1103
|
}
|
1112
1104
|
}
|
1113
|
-
|
1105
|
+
|
1114
1106
|
string serializeEnvvarsFromPoolOptions(const Options &options) const {
|
1115
1107
|
vector< pair<StaticString, StaticString> >::const_iterator it, end;
|
1116
1108
|
string result;
|
1117
|
-
|
1109
|
+
|
1118
1110
|
appendNullTerminatedKeyValue(result, "IN_PASSENGER", "1");
|
1119
1111
|
appendNullTerminatedKeyValue(result, "PYTHONUNBUFFERED", "1");
|
1120
1112
|
appendNullTerminatedKeyValue(result, "NODE_PATH", config->resourceLocator.getNodeLibDir());
|
@@ -1134,14 +1126,14 @@ protected:
|
|
1134
1126
|
"PASSENGER_BASE_URI",
|
1135
1127
|
options.baseURI);
|
1136
1128
|
}
|
1137
|
-
|
1129
|
+
|
1138
1130
|
it = options.environmentVariables.begin();
|
1139
1131
|
end = options.environmentVariables.end();
|
1140
1132
|
while (it != end) {
|
1141
1133
|
appendNullTerminatedKeyValue(result, it->first, it->second);
|
1142
1134
|
it++;
|
1143
1135
|
}
|
1144
|
-
|
1136
|
+
|
1145
1137
|
return Base64::encode(result);
|
1146
1138
|
}
|
1147
1139
|
|
@@ -1189,7 +1181,7 @@ protected:
|
|
1189
1181
|
fflush(stdout);
|
1190
1182
|
_exit(1);
|
1191
1183
|
}
|
1192
|
-
|
1184
|
+
|
1193
1185
|
// We set these environment variables here instead of
|
1194
1186
|
// in the SpawnPreparer because SpawnPreparer might
|
1195
1187
|
// be executed by bash, but these environment variables
|
@@ -1200,7 +1192,7 @@ protected:
|
|
1200
1192
|
setenv("HOME", info.home.c_str(), 1);
|
1201
1193
|
}
|
1202
1194
|
}
|
1203
|
-
|
1195
|
+
|
1204
1196
|
void setChroot(const SpawnPreparationInfo &info) {
|
1205
1197
|
if (info.chrootDir != "/") {
|
1206
1198
|
int ret = chroot(info.chrootDir.c_str());
|
@@ -1215,7 +1207,7 @@ protected:
|
|
1215
1207
|
}
|
1216
1208
|
}
|
1217
1209
|
}
|
1218
|
-
|
1210
|
+
|
1219
1211
|
void setWorkingDirectory(const SpawnPreparationInfo &info) {
|
1220
1212
|
vector<string>::const_iterator it, end = info.appRootPathsInsideChroot.end();
|
1221
1213
|
int ret;
|
@@ -1279,7 +1271,7 @@ protected:
|
|
1279
1271
|
_exit(1);
|
1280
1272
|
}
|
1281
1273
|
}
|
1282
|
-
|
1274
|
+
|
1283
1275
|
/**
|
1284
1276
|
* Execute the process spawning negotiation protocol.
|
1285
1277
|
*/
|
@@ -1290,7 +1282,7 @@ protected:
|
|
1290
1282
|
config->randomGenerator->generateAsciiString(11);
|
1291
1283
|
details.connectPassword = config->randomGenerator->generateAsciiString(43);
|
1292
1284
|
details.timeout = details.options->startTimeout * 1000;
|
1293
|
-
|
1285
|
+
|
1294
1286
|
string result;
|
1295
1287
|
try {
|
1296
1288
|
result = readMessageLine(details);
|
@@ -1306,7 +1298,7 @@ protected:
|
|
1306
1298
|
SpawnException::APP_STARTUP_TIMEOUT,
|
1307
1299
|
details);
|
1308
1300
|
}
|
1309
|
-
|
1301
|
+
|
1310
1302
|
protocol_begin:
|
1311
1303
|
if (result == "I have control 1.0\n") {
|
1312
1304
|
UPDATE_TRACE_POINT();
|
@@ -1344,11 +1336,11 @@ protected:
|
|
1344
1336
|
}
|
1345
1337
|
return ProcessPtr(); // Never reached.
|
1346
1338
|
}
|
1347
|
-
|
1339
|
+
|
1348
1340
|
void handleSpawnErrorResponse(NegotiationDetails &details) {
|
1349
1341
|
TRACE_POINT();
|
1350
1342
|
map<string, string> attributes;
|
1351
|
-
|
1343
|
+
|
1352
1344
|
while (true) {
|
1353
1345
|
string line = readMessageLine(details);
|
1354
1346
|
if (line.empty()) {
|
@@ -1366,7 +1358,7 @@ protected:
|
|
1366
1358
|
} else if (line == "\n") {
|
1367
1359
|
break;
|
1368
1360
|
}
|
1369
|
-
|
1361
|
+
|
1370
1362
|
string::size_type pos = line.find(": ");
|
1371
1363
|
if (pos == string::npos) {
|
1372
1364
|
throwAppSpawnException("An error occurred while starting the "
|
@@ -1375,12 +1367,12 @@ protected:
|
|
1375
1367
|
SpawnException::APP_STARTUP_PROTOCOL_ERROR,
|
1376
1368
|
details);
|
1377
1369
|
}
|
1378
|
-
|
1370
|
+
|
1379
1371
|
string key = line.substr(0, pos);
|
1380
1372
|
string value = line.substr(pos + 2, line.size() - pos - 3);
|
1381
1373
|
attributes[key] = value;
|
1382
1374
|
}
|
1383
|
-
|
1375
|
+
|
1384
1376
|
try {
|
1385
1377
|
string message = details.io.readAll(&details.timeout);
|
1386
1378
|
SpawnException e("An error occured while starting the web application.",
|
@@ -1404,7 +1396,7 @@ protected:
|
|
1404
1396
|
details);
|
1405
1397
|
}
|
1406
1398
|
}
|
1407
|
-
|
1399
|
+
|
1408
1400
|
void handleInvalidSpawnResponseType(const string &line, NegotiationDetails &details) {
|
1409
1401
|
if (line.empty()) {
|
1410
1402
|
throwAppSpawnException("An error occurred while starting "
|
@@ -1420,7 +1412,7 @@ protected:
|
|
1420
1412
|
details);
|
1421
1413
|
}
|
1422
1414
|
}
|
1423
|
-
|
1415
|
+
|
1424
1416
|
public:
|
1425
1417
|
/**
|
1426
1418
|
* Timestamp at which this Spawner was created. Microseconds resolution.
|
@@ -1431,10 +1423,10 @@ public:
|
|
1431
1423
|
: config(_config),
|
1432
1424
|
creationTime(SystemTime::getUsec())
|
1433
1425
|
{ }
|
1434
|
-
|
1426
|
+
|
1435
1427
|
virtual ~Spawner() { }
|
1436
1428
|
virtual ProcessPtr spawn(const Options &options) = 0;
|
1437
|
-
|
1429
|
+
|
1438
1430
|
/** Does not depend on the event loop. */
|
1439
1431
|
virtual bool cleanable() const {
|
1440
1432
|
return false;
|