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
data/ext/common/StaticString.h
CHANGED
@@ -36,6 +36,8 @@ namespace Passenger {
|
|
36
36
|
|
37
37
|
using namespace std;
|
38
38
|
|
39
|
+
#define P_STATIC_STRING(x) Passenger::StaticString(x, sizeof(x) - 1)
|
40
|
+
|
39
41
|
/**
|
40
42
|
* An immutable, static byte buffer. This class will never copy data:
|
41
43
|
* it just holds a pointer to the data. So a StaticString will become unusable
|
@@ -47,7 +49,7 @@ class StaticString {
|
|
47
49
|
private:
|
48
50
|
const char *content;
|
49
51
|
string::size_type len;
|
50
|
-
|
52
|
+
|
51
53
|
static const char *memmem(const char *haystack, string::size_type haystack_len,
|
52
54
|
const char *needle, string::size_type needle_len)
|
53
55
|
{
|
@@ -77,7 +79,7 @@ private:
|
|
77
79
|
}
|
78
80
|
} while (true);
|
79
81
|
}
|
80
|
-
|
82
|
+
|
81
83
|
public:
|
82
84
|
/** A hash function object for StaticString. */
|
83
85
|
struct Hash {
|
@@ -85,7 +87,7 @@ public:
|
|
85
87
|
const char *data = str.content;
|
86
88
|
const char *end = str.content + str.len;
|
87
89
|
size_t result = 0;
|
88
|
-
|
90
|
+
|
89
91
|
#if defined(__i386__) || defined(__x86_64__)
|
90
92
|
/* When on x86 or x86_64, process 4 or 8 bytes
|
91
93
|
* per iteration by treating the data as an
|
@@ -96,15 +98,15 @@ public:
|
|
96
98
|
const char *last_long = str.content +
|
97
99
|
str.len / sizeof(unsigned long) *
|
98
100
|
sizeof(unsigned long);
|
99
|
-
|
101
|
+
|
100
102
|
while (data < last_long) {
|
101
103
|
result = result * 33 + *((unsigned long *) data);
|
102
104
|
data += sizeof(unsigned long);
|
103
105
|
}
|
104
|
-
|
106
|
+
|
105
107
|
/* Process leftover data byte-by-byte. */
|
106
108
|
#endif
|
107
|
-
|
109
|
+
|
108
110
|
while (data < end) {
|
109
111
|
result = result * 33 + *data;
|
110
112
|
data++;
|
@@ -112,68 +114,68 @@ public:
|
|
112
114
|
return result;
|
113
115
|
}
|
114
116
|
};
|
115
|
-
|
116
|
-
StaticString()
|
117
|
-
content
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
StaticString(const StaticString &b)
|
122
|
-
content
|
123
|
-
|
124
|
-
|
125
|
-
|
117
|
+
|
118
|
+
StaticString()
|
119
|
+
: content(""),
|
120
|
+
len(0)
|
121
|
+
{ }
|
122
|
+
|
123
|
+
StaticString(const StaticString &b)
|
124
|
+
: content(b.content),
|
125
|
+
len(b.len)
|
126
|
+
{ }
|
127
|
+
|
126
128
|
StaticString(const string &s) {
|
127
129
|
content = s.data();
|
128
130
|
len = s.size();
|
129
131
|
}
|
130
|
-
|
132
|
+
|
131
133
|
StaticString(const char *data) {
|
132
134
|
content = data;
|
133
135
|
len = strlen(data);
|
134
136
|
}
|
135
|
-
|
136
|
-
StaticString(const char *data, string::size_type
|
137
|
-
content
|
138
|
-
|
139
|
-
|
140
|
-
|
137
|
+
|
138
|
+
StaticString(const char *data, string::size_type _len)
|
139
|
+
: content(data),
|
140
|
+
len(_len)
|
141
|
+
{ }
|
142
|
+
|
141
143
|
bool empty() const {
|
142
144
|
return len == 0;
|
143
145
|
}
|
144
|
-
|
146
|
+
|
145
147
|
string::size_type size() const {
|
146
148
|
return len;
|
147
149
|
}
|
148
|
-
|
150
|
+
|
149
151
|
char operator[](string::size_type i) const {
|
150
152
|
return content[i];
|
151
153
|
}
|
152
|
-
|
154
|
+
|
153
155
|
char at(string::size_type i) const {
|
154
156
|
return content[i];
|
155
157
|
}
|
156
|
-
|
158
|
+
|
157
159
|
const char *c_str() const {
|
158
160
|
return content;
|
159
161
|
}
|
160
|
-
|
162
|
+
|
161
163
|
const char *data() const {
|
162
164
|
return content;
|
163
165
|
}
|
164
|
-
|
166
|
+
|
165
167
|
string toString() const {
|
166
168
|
return string(content, len);
|
167
169
|
}
|
168
|
-
|
170
|
+
|
169
171
|
bool equals(const StaticString &other) const {
|
170
172
|
return len == other.len && memcmp(content, other.content, len) == 0;
|
171
173
|
}
|
172
|
-
|
174
|
+
|
173
175
|
bool equals(const string &other) const {
|
174
176
|
return len == other.size() && memcmp(content, other.data(), len) == 0;
|
175
177
|
}
|
176
|
-
|
178
|
+
|
177
179
|
string::size_type find(char c, string::size_type pos = 0) const {
|
178
180
|
if (pos < len) {
|
179
181
|
const char *result = (const char *) memchr(content + pos, c, len - pos);
|
@@ -186,7 +188,7 @@ public:
|
|
186
188
|
return string::npos;
|
187
189
|
}
|
188
190
|
}
|
189
|
-
|
191
|
+
|
190
192
|
string::size_type find(const StaticString &s, string::size_type pos = 0) const {
|
191
193
|
if (s.empty()) {
|
192
194
|
return 0;
|
@@ -201,11 +203,11 @@ public:
|
|
201
203
|
return string::npos;
|
202
204
|
}
|
203
205
|
}
|
204
|
-
|
206
|
+
|
205
207
|
string::size_type find(const char *s, string::size_type pos, string::size_type n) const {
|
206
208
|
return find(StaticString(s, n), pos);
|
207
209
|
}
|
208
|
-
|
210
|
+
|
209
211
|
StaticString substr(string::size_type pos = 0, string::size_type n = string::npos) const {
|
210
212
|
if (pos > len) {
|
211
213
|
throw out_of_range("Argument 'pos' out of range");
|
@@ -216,33 +218,33 @@ public:
|
|
216
218
|
return StaticString(content + pos, n);
|
217
219
|
}
|
218
220
|
}
|
219
|
-
|
221
|
+
|
220
222
|
bool operator==(const StaticString &other) const {
|
221
223
|
return len == other.len && memcmp(content, other.content, len) == 0;
|
222
224
|
}
|
223
|
-
|
225
|
+
|
224
226
|
bool operator==(const string &other) const {
|
225
227
|
return len == other.size() && memcmp(content, other.data(), len) == 0;
|
226
228
|
}
|
227
|
-
|
229
|
+
|
228
230
|
bool operator==(const char *other) const {
|
229
231
|
size_t other_len = strlen(other);
|
230
232
|
return len == other_len && memcmp(content, other, other_len) == 0;
|
231
233
|
}
|
232
|
-
|
234
|
+
|
233
235
|
bool operator!=(const StaticString &other) const {
|
234
236
|
return len != other.len || memcmp(content, other.content, len) != 0;
|
235
237
|
}
|
236
|
-
|
238
|
+
|
237
239
|
bool operator!=(const string &other) const {
|
238
240
|
return len != other.size() || memcmp(content, other.data(), len) != 0;
|
239
241
|
}
|
240
|
-
|
242
|
+
|
241
243
|
bool operator!=(const char *other) const {
|
242
244
|
size_t other_len = strlen(other);
|
243
245
|
return len != other_len || memcmp(content, other, other_len) != 0;
|
244
246
|
}
|
245
|
-
|
247
|
+
|
246
248
|
bool operator<(const StaticString &other) const {
|
247
249
|
size_t size = (len < other.size()) ? len : other.size();
|
248
250
|
int result = memcmp(content, other.data(), size);
|
@@ -252,25 +254,25 @@ public:
|
|
252
254
|
return result < 0;
|
253
255
|
}
|
254
256
|
}
|
255
|
-
|
257
|
+
|
256
258
|
bool operator<(const char *other) const {
|
257
259
|
return *this < StaticString(other);
|
258
260
|
}
|
259
|
-
|
261
|
+
|
260
262
|
string operator+(const char *other) const {
|
261
263
|
return string(content, len) + other;
|
262
264
|
}
|
263
|
-
|
265
|
+
|
264
266
|
string operator+(const string &other) const {
|
265
267
|
return string(content, len) + other;
|
266
268
|
}
|
267
|
-
|
269
|
+
|
268
270
|
string operator+(const StaticString &other) const {
|
269
271
|
string result(content, len);
|
270
272
|
result.append(other.data(), other.size());
|
271
273
|
return result;
|
272
274
|
}
|
273
|
-
|
275
|
+
|
274
276
|
operator string() const {
|
275
277
|
return string(content, len);
|
276
278
|
}
|
data/ext/common/Utils.cpp
CHANGED
@@ -27,6 +27,7 @@
|
|
27
27
|
#include <boost/thread.hpp>
|
28
28
|
#include <boost/shared_array.hpp>
|
29
29
|
|
30
|
+
#include <algorithm>
|
30
31
|
#include <cassert>
|
31
32
|
#include <cstdlib>
|
32
33
|
#include <cstring>
|
@@ -90,12 +91,12 @@ namespace {
|
|
90
91
|
struct FileGuard {
|
91
92
|
string filename;
|
92
93
|
bool committed;
|
93
|
-
|
94
|
+
|
94
95
|
FileGuard(const string &filename) {
|
95
96
|
this->filename = filename;
|
96
97
|
committed = false;
|
97
98
|
}
|
98
|
-
|
99
|
+
|
99
100
|
~FileGuard() {
|
100
101
|
if (!committed) {
|
101
102
|
int ret;
|
@@ -104,7 +105,7 @@ namespace {
|
|
104
105
|
} while (ret == -1 && errno == EINTR);
|
105
106
|
}
|
106
107
|
}
|
107
|
-
|
108
|
+
|
108
109
|
void commit() {
|
109
110
|
committed = true;
|
110
111
|
}
|
@@ -120,7 +121,7 @@ FileType
|
|
120
121
|
getFileType(const StaticString &filename, CachedFileStat *cstat, unsigned int throttleRate) {
|
121
122
|
struct stat buf;
|
122
123
|
int ret;
|
123
|
-
|
124
|
+
|
124
125
|
if (cstat != NULL) {
|
125
126
|
ret = cstat->stat(filename, &buf, throttleRate);
|
126
127
|
} else {
|
@@ -153,7 +154,7 @@ createFile(const string &filename, const StaticString &contents, mode_t permissi
|
|
153
154
|
{
|
154
155
|
FileDescriptor fd;
|
155
156
|
int ret, e, options;
|
156
|
-
|
157
|
+
|
157
158
|
options = O_WRONLY | O_CREAT | O_TRUNC;
|
158
159
|
if (!overwrite) {
|
159
160
|
options |= O_EXCL;
|
@@ -163,7 +164,7 @@ createFile(const string &filename, const StaticString &contents, mode_t permissi
|
|
163
164
|
} while (fd == -1 && errno == EINTR);
|
164
165
|
if (fd != -1) {
|
165
166
|
FileGuard guard(filename);
|
166
|
-
|
167
|
+
|
167
168
|
// The file permission may not be as expected because of the active
|
168
169
|
// umask, so fchmod() it here to ensure correct permissions.
|
169
170
|
do {
|
@@ -174,7 +175,7 @@ createFile(const string &filename, const StaticString &contents, mode_t permissi
|
|
174
175
|
throw FileSystemException("Cannot set permissions on " + filename,
|
175
176
|
e, filename);
|
176
177
|
}
|
177
|
-
|
178
|
+
|
178
179
|
if (owner != USER_NOT_GIVEN && group != GROUP_NOT_GIVEN) {
|
179
180
|
if (owner == USER_NOT_GIVEN) {
|
180
181
|
owner = (uid_t) -1; // Don't let fchown change file owner.
|
@@ -191,7 +192,7 @@ createFile(const string &filename, const StaticString &contents, mode_t permissi
|
|
191
192
|
e, filename);
|
192
193
|
}
|
193
194
|
}
|
194
|
-
|
195
|
+
|
195
196
|
try {
|
196
197
|
writeExact(fd, contents);
|
197
198
|
fd.close();
|
@@ -219,7 +220,7 @@ canonicalizePath(const string &path) {
|
|
219
220
|
if (tmp == NULL) {
|
220
221
|
int e = errno;
|
221
222
|
string message;
|
222
|
-
|
223
|
+
|
223
224
|
message = "Cannot resolve the path '";
|
224
225
|
message.append(path);
|
225
226
|
message.append("'");
|
@@ -234,7 +235,7 @@ canonicalizePath(const string &path) {
|
|
234
235
|
if (realpath(path.c_str(), tmp) == NULL) {
|
235
236
|
int e = errno;
|
236
237
|
string message;
|
237
|
-
|
238
|
+
|
238
239
|
message = "Cannot resolve the path '";
|
239
240
|
message.append(path);
|
240
241
|
message.append("'");
|
@@ -249,7 +250,7 @@ string
|
|
249
250
|
resolveSymlink(const StaticString &path) {
|
250
251
|
char buf[PATH_MAX];
|
251
252
|
ssize_t size;
|
252
|
-
|
253
|
+
|
253
254
|
size = readlink(path.c_str(), buf, sizeof(buf) - 1);
|
254
255
|
if (size == -1) {
|
255
256
|
if (errno == EINVAL) {
|
@@ -347,10 +348,10 @@ escapeForXml(const StaticString &input) {
|
|
347
348
|
string::size_type input_pos = 0;
|
348
349
|
string::size_type input_end_pos = input.size();
|
349
350
|
string::size_type result_pos = 0;
|
350
|
-
|
351
|
+
|
351
352
|
while (input_pos < input_end_pos) {
|
352
353
|
const unsigned char ch = input[input_pos];
|
353
|
-
|
354
|
+
|
354
355
|
if ((ch >= 'A' && ch <= 'z')
|
355
356
|
|| (ch >= '0' && ch <= '9')
|
356
357
|
|| ch == '/' || ch == ' ' || ch == '_' || ch == '.'
|
@@ -362,7 +363,7 @@ escapeForXml(const StaticString &input) {
|
|
362
363
|
// Not an ASCII character; escape it.
|
363
364
|
char escapedCharacter[sizeof("ÿ") + 1];
|
364
365
|
int size;
|
365
|
-
|
366
|
+
|
366
367
|
size = snprintf(escapedCharacter,
|
367
368
|
sizeof(escapedCharacter) - 1,
|
368
369
|
"&#%d;",
|
@@ -371,13 +372,13 @@ escapeForXml(const StaticString &input) {
|
|
371
372
|
throw std::bad_alloc();
|
372
373
|
}
|
373
374
|
escapedCharacter[sizeof(escapedCharacter) - 1] = '\0';
|
374
|
-
|
375
|
+
|
375
376
|
result.replace(result_pos, 1, escapedCharacter, size);
|
376
377
|
result_pos += size;
|
377
378
|
}
|
378
379
|
input_pos++;
|
379
380
|
}
|
380
|
-
|
381
|
+
|
381
382
|
return result;
|
382
383
|
}
|
383
384
|
|
@@ -387,11 +388,9 @@ getProcessUsername() {
|
|
387
388
|
long bufSize;
|
388
389
|
shared_array<char> strings;
|
389
390
|
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
bufSize = 1024 * 64;
|
394
|
-
}
|
391
|
+
// _SC_GETPW_R_SIZE_MAX is not a maximum:
|
392
|
+
// http://tomlee.co/2012/10/problems-with-large-linux-unix-groups-and-getgrgid_r-getgrnam_r/
|
393
|
+
bufSize = std::max<long>(1024 * 128, sysconf(_SC_GETPW_R_SIZE_MAX));
|
395
394
|
strings.reset(new char[bufSize]);
|
396
395
|
|
397
396
|
result = (struct passwd *) NULL;
|
@@ -414,11 +413,9 @@ getGroupName(gid_t gid) {
|
|
414
413
|
long bufSize;
|
415
414
|
shared_array<char> strings;
|
416
415
|
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
bufSize = 1024 * 64;
|
421
|
-
}
|
416
|
+
// _SC_GETGR_R_SIZE_MAX is not a maximum:
|
417
|
+
// http://tomlee.co/2012/10/problems-with-large-linux-unix-groups-and-getgrgid_r-getgrnam_r/
|
418
|
+
bufSize = std::max<long>(1024 * 128, sysconf(_SC_GETGR_R_SIZE_MAX));
|
422
419
|
strings.reset(new char[bufSize]);
|
423
420
|
|
424
421
|
groupEntry = (struct group *) NULL;
|
@@ -439,11 +436,9 @@ lookupGid(const string &groupName) {
|
|
439
436
|
long bufSize;
|
440
437
|
shared_array<char> strings;
|
441
438
|
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
bufSize = 1024 * 64;
|
446
|
-
}
|
439
|
+
// _SC_GETGR_R_SIZE_MAX is not a maximum:
|
440
|
+
// http://tomlee.co/2012/10/problems-with-large-linux-unix-groups-and-getgrgid_r-getgrnam_r/
|
441
|
+
bufSize = std::max<long>(1024 * 128, sysconf(_SC_GETGR_R_SIZE_MAX));
|
447
442
|
strings.reset(new char[bufSize]);
|
448
443
|
|
449
444
|
groupEntry = (struct group *) NULL;
|
@@ -467,17 +462,17 @@ parseModeString(const StaticString &mode) {
|
|
467
462
|
mode_t modeBits = 0;
|
468
463
|
vector<string> clauses;
|
469
464
|
vector<string>::iterator it;
|
470
|
-
|
465
|
+
|
471
466
|
split(mode, ',', clauses);
|
472
467
|
for (it = clauses.begin(); it != clauses.end(); it++) {
|
473
468
|
const string &clause = *it;
|
474
|
-
|
469
|
+
|
475
470
|
if (clause.empty()) {
|
476
471
|
continue;
|
477
472
|
} else if (clause.size() < 2 || (clause[0] != '+' && clause[1] != '=')) {
|
478
473
|
throw InvalidModeStringException("Invalid mode clause specification '" + clause + "'");
|
479
474
|
}
|
480
|
-
|
475
|
+
|
481
476
|
switch (clause[0]) {
|
482
477
|
case 'u':
|
483
478
|
for (string::size_type i = 2; i < clause.size(); i++) {
|
@@ -564,7 +559,7 @@ parseModeString(const StaticString &mode) {
|
|
564
559
|
"' in mode clause specification '" + clause + "'");
|
565
560
|
}
|
566
561
|
}
|
567
|
-
|
562
|
+
|
568
563
|
return modeBits;
|
569
564
|
}
|
570
565
|
|
@@ -648,13 +643,13 @@ makeDirTree(const string &path, const StaticString &mode, uid_t owner, gid_t gro
|
|
648
643
|
string current = path;
|
649
644
|
mode_t modeBits;
|
650
645
|
int ret;
|
651
|
-
|
646
|
+
|
652
647
|
if (stat(path.c_str(), &buf) == 0) {
|
653
648
|
return;
|
654
649
|
}
|
655
|
-
|
650
|
+
|
656
651
|
modeBits = parseModeString(mode);
|
657
|
-
|
652
|
+
|
658
653
|
/* Create a list of parent paths that don't exist. For example, given
|
659
654
|
* path == "/a/b/c/d/e" and that only /a exists, the list will become
|
660
655
|
* as follows:
|
@@ -667,11 +662,11 @@ makeDirTree(const string &path, const StaticString &mode, uid_t owner, gid_t gro
|
|
667
662
|
paths.push_back(current);
|
668
663
|
current = extractDirName(current);
|
669
664
|
}
|
670
|
-
|
665
|
+
|
671
666
|
/* Now traverse the list in reverse order and create directories that don't exist. */
|
672
667
|
for (rit = paths.rbegin(); rit != paths.rend(); rit++) {
|
673
668
|
current = *rit;
|
674
|
-
|
669
|
+
|
675
670
|
do {
|
676
671
|
ret = mkdir(current.c_str(), modeBits);
|
677
672
|
} while (ret == -1 && errno == EINTR);
|
@@ -685,12 +680,12 @@ makeDirTree(const string &path, const StaticString &mode, uid_t owner, gid_t gro
|
|
685
680
|
e, current);
|
686
681
|
}
|
687
682
|
}
|
688
|
-
|
683
|
+
|
689
684
|
/* Chmod in order to override the umask. */
|
690
685
|
do {
|
691
686
|
ret = chmod(current.c_str(), modeBits);
|
692
687
|
} while (ret == -1 && errno == EINTR);
|
693
|
-
|
688
|
+
|
694
689
|
if (owner != USER_NOT_GIVEN && group != GROUP_NOT_GIVEN) {
|
695
690
|
if (owner == USER_NOT_GIVEN) {
|
696
691
|
owner = (uid_t) -1; // Don't let chown change file owner.
|
@@ -704,7 +699,7 @@ makeDirTree(const string &path, const StaticString &mode, uid_t owner, gid_t gro
|
|
704
699
|
if (ret == -1) {
|
705
700
|
char message[1024];
|
706
701
|
int e = errno;
|
707
|
-
|
702
|
+
|
708
703
|
snprintf(message, sizeof(message) - 1,
|
709
704
|
"Cannot change the directory '%s' its UID to %lld and GID to %lld",
|
710
705
|
current.c_str(), (long long) owner, (long long) group);
|
@@ -779,32 +774,32 @@ prestartWebApps(const ResourceLocator &locator, const string &ruby,
|
|
779
774
|
* executing the prespawning scripts.
|
780
775
|
*/
|
781
776
|
syscalls::sleep(2);
|
782
|
-
|
777
|
+
|
783
778
|
this_thread::disable_interruption di;
|
784
779
|
this_thread::disable_syscall_interruption dsi;
|
785
780
|
vector<string>::const_iterator it;
|
786
781
|
string prespawnScript = locator.getHelperScriptsDir() + "/prespawn";
|
787
|
-
|
782
|
+
|
788
783
|
it = prestartURLs.begin();
|
789
784
|
while (it != prestartURLs.end() && !this_thread::interruption_requested()) {
|
790
785
|
if (it->empty()) {
|
791
786
|
it++;
|
792
787
|
continue;
|
793
788
|
}
|
794
|
-
|
789
|
+
|
795
790
|
pid_t pid;
|
796
|
-
|
791
|
+
|
797
792
|
pid = fork();
|
798
793
|
if (pid == 0) {
|
799
794
|
long max_fds, i;
|
800
795
|
int e;
|
801
|
-
|
796
|
+
|
802
797
|
// Close all unnecessary file descriptors.
|
803
798
|
max_fds = sysconf(_SC_OPEN_MAX);
|
804
799
|
for (i = 3; i < max_fds; i++) {
|
805
800
|
syscalls::close(i);
|
806
801
|
}
|
807
|
-
|
802
|
+
|
808
803
|
execlp(ruby.c_str(),
|
809
804
|
ruby.c_str(),
|
810
805
|
prespawnScript.c_str(),
|
@@ -829,7 +824,7 @@ prestartWebApps(const ResourceLocator &locator, const string &ruby,
|
|
829
824
|
throw;
|
830
825
|
}
|
831
826
|
}
|
832
|
-
|
827
|
+
|
833
828
|
this_thread::restore_interruption si(di);
|
834
829
|
this_thread::restore_syscall_interruption ssi(dsi);
|
835
830
|
syscalls::sleep(1);
|
@@ -962,7 +957,7 @@ resetSignalHandlersAndMask() {
|
|
962
957
|
|
963
958
|
sigset_t signal_set;
|
964
959
|
int ret;
|
965
|
-
|
960
|
+
|
966
961
|
sigemptyset(&signal_set);
|
967
962
|
do {
|
968
963
|
ret = sigprocmask(SIG_SETMASK, &signal_set, NULL);
|
@@ -1033,9 +1028,9 @@ runCommandAndCaptureOutput(const char **command) {
|
|
1033
1028
|
pid_t pid;
|
1034
1029
|
int e;
|
1035
1030
|
Pipe p;
|
1036
|
-
|
1031
|
+
|
1037
1032
|
p = createPipe();
|
1038
|
-
|
1033
|
+
|
1039
1034
|
this_thread::disable_syscall_interruption dsi;
|
1040
1035
|
pid = syscalls::fork();
|
1041
1036
|
if (pid == 0) {
|
@@ -1060,12 +1055,12 @@ runCommandAndCaptureOutput(const char **command) {
|
|
1060
1055
|
} else {
|
1061
1056
|
bool done = false;
|
1062
1057
|
string result;
|
1063
|
-
|
1058
|
+
|
1064
1059
|
p[1].close();
|
1065
1060
|
while (!done) {
|
1066
1061
|
char buf[1024 * 4];
|
1067
1062
|
ssize_t ret;
|
1068
|
-
|
1063
|
+
|
1069
1064
|
try {
|
1070
1065
|
this_thread::restore_syscall_interruption rsi(dsi);
|
1071
1066
|
ret = syscalls::read(p[0], buf, sizeof(buf));
|
@@ -1086,7 +1081,7 @@ runCommandAndCaptureOutput(const char **command) {
|
|
1086
1081
|
}
|
1087
1082
|
p[0].close();
|
1088
1083
|
syscalls::waitpid(pid, NULL, 0);
|
1089
|
-
|
1084
|
+
|
1090
1085
|
if (result.empty()) {
|
1091
1086
|
throw RuntimeException(string("The '") + command[1] +
|
1092
1087
|
"' command failed");
|
@@ -1123,7 +1118,7 @@ asyncFork() {
|
|
1123
1118
|
static int
|
1124
1119
|
getFileDescriptorLimit() {
|
1125
1120
|
long long sysconfResult = sysconf(_SC_OPEN_MAX);
|
1126
|
-
|
1121
|
+
|
1127
1122
|
struct rlimit rl;
|
1128
1123
|
long long rlimitResult;
|
1129
1124
|
if (getrlimit(RLIMIT_NOFILE, &rl) == -1) {
|
@@ -1131,7 +1126,7 @@ getFileDescriptorLimit() {
|
|
1131
1126
|
} else {
|
1132
1127
|
rlimitResult = (long long) rl.rlim_max;
|
1133
1128
|
}
|
1134
|
-
|
1129
|
+
|
1135
1130
|
long result;
|
1136
1131
|
// OS X 10.9 returns LLONG_MAX. It doesn't make sense
|
1137
1132
|
// to use that result so we limit ourselves to the
|
@@ -1159,7 +1154,7 @@ static int
|
|
1159
1154
|
getHighestFileDescriptor(bool asyncSignalSafe) {
|
1160
1155
|
#if defined(F_MAXFD)
|
1161
1156
|
int ret;
|
1162
|
-
|
1157
|
+
|
1163
1158
|
do {
|
1164
1159
|
ret = fcntl(0, F_MAXFD);
|
1165
1160
|
} while (ret == -1 && errno == EINTR);
|
@@ -1167,17 +1162,17 @@ getHighestFileDescriptor(bool asyncSignalSafe) {
|
|
1167
1162
|
ret = getFileDescriptorLimit();
|
1168
1163
|
}
|
1169
1164
|
return ret;
|
1170
|
-
|
1165
|
+
|
1171
1166
|
#else
|
1172
1167
|
int p[2], ret, flags;
|
1173
1168
|
pid_t pid = -1;
|
1174
1169
|
int result = -1;
|
1175
|
-
|
1170
|
+
|
1176
1171
|
/* Since opendir() may not be async signal safe and thus may lock up
|
1177
1172
|
* or crash, we use it in a child process which we kill if we notice
|
1178
1173
|
* that things are going wrong.
|
1179
1174
|
*/
|
1180
|
-
|
1175
|
+
|
1181
1176
|
// Make a pipe.
|
1182
1177
|
p[0] = p[1] = -1;
|
1183
1178
|
do {
|
@@ -1186,7 +1181,7 @@ getHighestFileDescriptor(bool asyncSignalSafe) {
|
|
1186
1181
|
if (ret == -1) {
|
1187
1182
|
goto done;
|
1188
1183
|
}
|
1189
|
-
|
1184
|
+
|
1190
1185
|
// Make the read side non-blocking.
|
1191
1186
|
do {
|
1192
1187
|
flags = fcntl(p[0], F_GETFL);
|
@@ -1200,7 +1195,7 @@ getHighestFileDescriptor(bool asyncSignalSafe) {
|
|
1200
1195
|
if (ret == -1) {
|
1201
1196
|
goto done;
|
1202
1197
|
}
|
1203
|
-
|
1198
|
+
|
1204
1199
|
if (asyncSignalSafe) {
|
1205
1200
|
do {
|
1206
1201
|
pid = asyncFork();
|
@@ -1210,12 +1205,12 @@ getHighestFileDescriptor(bool asyncSignalSafe) {
|
|
1210
1205
|
pid = fork();
|
1211
1206
|
} while (pid == -1 && errno == EINTR);
|
1212
1207
|
}
|
1213
|
-
|
1208
|
+
|
1214
1209
|
if (pid == 0) {
|
1215
1210
|
// Don't close p[0] here or it might affect the result.
|
1216
|
-
|
1211
|
+
|
1217
1212
|
resetSignalHandlersAndMask();
|
1218
|
-
|
1213
|
+
|
1219
1214
|
struct sigaction action;
|
1220
1215
|
action.sa_handler = _exit;
|
1221
1216
|
action.sa_flags = SA_RESTART;
|
@@ -1226,7 +1221,7 @@ getHighestFileDescriptor(bool asyncSignalSafe) {
|
|
1226
1221
|
sigaction(SIGILL, &action, NULL);
|
1227
1222
|
sigaction(SIGFPE, &action, NULL);
|
1228
1223
|
sigaction(SIGABRT, &action, NULL);
|
1229
|
-
|
1224
|
+
|
1230
1225
|
DIR *dir = NULL;
|
1231
1226
|
#ifdef __APPLE__
|
1232
1227
|
/* /dev/fd can always be trusted on OS X. */
|
@@ -1253,14 +1248,14 @@ getHighestFileDescriptor(bool asyncSignalSafe) {
|
|
1253
1248
|
_exit(1);
|
1254
1249
|
}
|
1255
1250
|
}
|
1256
|
-
|
1251
|
+
|
1257
1252
|
struct dirent *ent;
|
1258
1253
|
union {
|
1259
1254
|
int highest;
|
1260
1255
|
char data[sizeof(int)];
|
1261
1256
|
} u;
|
1262
1257
|
u.highest = -1;
|
1263
|
-
|
1258
|
+
|
1264
1259
|
while ((ent = readdir(dir)) != NULL) {
|
1265
1260
|
if (ent->d_name[0] != '.') {
|
1266
1261
|
int number = atoi(ent->d_name);
|
@@ -1281,14 +1276,14 @@ getHighestFileDescriptor(bool asyncSignalSafe) {
|
|
1281
1276
|
}
|
1282
1277
|
closedir(dir);
|
1283
1278
|
_exit(0);
|
1284
|
-
|
1279
|
+
|
1285
1280
|
} else if (pid == -1) {
|
1286
1281
|
goto done;
|
1287
|
-
|
1282
|
+
|
1288
1283
|
} else {
|
1289
1284
|
close(p[1]); // Do not retry on EINTR: http://news.ycombinator.com/item?id=3363819
|
1290
1285
|
p[1] = -1;
|
1291
|
-
|
1286
|
+
|
1292
1287
|
union {
|
1293
1288
|
int highest;
|
1294
1289
|
char data[sizeof(int)];
|
@@ -1297,7 +1292,7 @@ getHighestFileDescriptor(bool asyncSignalSafe) {
|
|
1297
1292
|
struct pollfd pfd;
|
1298
1293
|
pfd.fd = p[0];
|
1299
1294
|
pfd.events = POLLIN;
|
1300
|
-
|
1295
|
+
|
1301
1296
|
do {
|
1302
1297
|
do {
|
1303
1298
|
// The child process must finish within 30 ms, otherwise
|
@@ -1307,7 +1302,7 @@ getHighestFileDescriptor(bool asyncSignalSafe) {
|
|
1307
1302
|
if (ret <= 0) {
|
1308
1303
|
goto done;
|
1309
1304
|
}
|
1310
|
-
|
1305
|
+
|
1311
1306
|
do {
|
1312
1307
|
ret = read(p[0], u.data + bytesRead, sizeof(int) - bytesRead);
|
1313
1308
|
} while (ret == -1 && ret == EINTR);
|
@@ -1321,7 +1316,7 @@ getHighestFileDescriptor(bool asyncSignalSafe) {
|
|
1321
1316
|
bytesRead += ret;
|
1322
1317
|
}
|
1323
1318
|
} while (bytesRead < (ssize_t) sizeof(int));
|
1324
|
-
|
1319
|
+
|
1325
1320
|
result = u.highest;
|
1326
1321
|
goto done;
|
1327
1322
|
}
|
@@ -1342,7 +1337,7 @@ done:
|
|
1342
1337
|
ret = waitpid(pid, NULL, 0);
|
1343
1338
|
} while (ret == -1 && errno == EINTR);
|
1344
1339
|
}
|
1345
|
-
|
1340
|
+
|
1346
1341
|
if (result == -1) {
|
1347
1342
|
result = getFileDescriptorLimit();
|
1348
1343
|
}
|
@@ -1364,7 +1359,7 @@ closeAllFileDescriptors(int lastToKeepOpen, bool asyncSignalSafe) {
|
|
1364
1359
|
closefrom(lastToKeepOpen + 1);
|
1365
1360
|
return;
|
1366
1361
|
#endif
|
1367
|
-
|
1362
|
+
|
1368
1363
|
for (int i = getHighestFileDescriptor(asyncSignalSafe); i > lastToKeepOpen; i--) {
|
1369
1364
|
/* Even though we normally shouldn't retry on EINTR
|
1370
1365
|
* (http://news.ycombinator.com/item?id=3363819)
|