passenger 3.9.2.beta → 4.0.0.rc4
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.
- data/.travis.yml +3 -0
- data/NEWS +77 -7
- data/README.md +3 -11
- data/bin/passenger-install-apache2-module +24 -20
- data/bin/passenger-install-nginx-module +25 -23
- data/build/agents.rb +11 -0
- data/build/apache2.rb +9 -5
- data/build/basics.rb +37 -30
- data/build/common_library.rb +4 -1
- data/build/cplusplus_support.rb +5 -5
- data/build/cxx_tests.rb +28 -8
- data/build/integration_tests.rb +6 -3
- data/build/nginx.rb +3 -3
- data/build/packaging.rb +95 -57
- data/build/ruby_extension.rb +34 -21
- data/build/ruby_tests.rb +4 -2
- data/build/test_basics.rb +1 -1
- data/dev/run_travis.sh +36 -1
- data/doc/Users guide Apache.html +425 -308
- data/doc/Users guide Apache.idmap.txt +78 -70
- data/doc/Users guide Apache.index.sqlite3 +0 -0
- data/doc/Users guide Apache.txt +33 -92
- data/doc/Users guide Nginx.html +519 -220
- data/doc/Users guide Nginx.idmap.txt +78 -60
- data/doc/Users guide Nginx.txt +115 -26
- data/doc/Users guide Standalone.html +8 -2
- data/doc/users_guide_snippets/analysis_and_system_maintenance.txt +1 -7
- data/doc/users_guide_snippets/installation.txt +167 -22
- data/doc/users_guide_snippets/rackup_specifications.txt +4 -0
- data/doc/users_guide_snippets/since_version.txt +1 -0
- data/doc/users_guide_snippets/support_information.txt +3 -7
- data/doc/users_guide_snippets/tips.txt +0 -24
- data/ext/apache2/Configuration.cpp +11 -33
- data/ext/apache2/Configuration.hpp +3 -18
- data/ext/apache2/DirectoryMapper.h +20 -70
- data/ext/apache2/Hooks.cpp +2 -2
- data/ext/common/AgentsStarter.cpp +0 -2
- data/ext/common/AgentsStarter.h +0 -1
- data/ext/common/AgentsStarter.hpp +1 -3
- data/ext/common/ApplicationPool2/AppTypes.cpp +74 -0
- data/ext/common/ApplicationPool2/AppTypes.h +202 -0
- data/ext/common/ApplicationPool2/Common.h +12 -10
- data/ext/common/ApplicationPool2/DirectSpawner.h +256 -0
- data/ext/common/ApplicationPool2/DummySpawner.h +90 -0
- data/ext/common/ApplicationPool2/Group.h +311 -94
- data/ext/common/ApplicationPool2/Implementation.cpp +405 -145
- data/ext/common/ApplicationPool2/Options.h +24 -26
- data/ext/common/ApplicationPool2/PipeWatcher.h +20 -13
- data/ext/common/ApplicationPool2/Pool.h +326 -183
- data/ext/common/ApplicationPool2/Process.h +205 -55
- data/ext/common/ApplicationPool2/README.md +1 -1
- data/ext/common/ApplicationPool2/Session.h +21 -10
- data/ext/common/ApplicationPool2/SmartSpawner.h +801 -0
- data/ext/common/ApplicationPool2/Spawner.h +141 -1149
- data/ext/common/ApplicationPool2/SpawnerFactory.h +132 -0
- data/ext/common/ApplicationPool2/SuperGroup.h +146 -223
- data/ext/common/Constants.h +4 -2
- data/ext/common/Exceptions.h +23 -1
- data/ext/common/Logging.cpp +17 -6
- data/ext/common/Logging.h +37 -7
- data/ext/common/ResourceLocator.h +1 -1
- data/ext/common/Utils.cpp +49 -1
- data/ext/common/Utils.h +13 -4
- data/ext/common/{AnsiColorConstants.h → Utils/AnsiColorConstants.h} +0 -0
- data/ext/common/{BCrypt.cpp → Utils/BCrypt.cpp} +0 -0
- data/ext/common/{BCrypt.h → Utils/BCrypt.h} +0 -0
- data/ext/common/{Blowfish.c → Utils/Blowfish.c} +0 -0
- data/ext/common/{Blowfish.h → Utils/Blowfish.h} +0 -0
- data/ext/common/Utils/CachedFileStat.hpp +27 -25
- data/ext/common/Utils/Curl.h +184 -0
- data/ext/common/{HttpConstants.h → Utils/HttpConstants.h} +3 -0
- data/ext/common/Utils/IOUtils.cpp +6 -2
- data/ext/common/{IniFile.h → Utils/IniFile.h} +0 -0
- data/ext/common/Utils/LargeFiles.cpp +30 -0
- data/ext/common/Utils/LargeFiles.h +40 -0
- data/ext/common/Utils/StrIntUtils.cpp +72 -8
- data/ext/common/Utils/StrIntUtils.h +24 -2
- data/ext/common/Utils/StringMap.h +12 -2
- data/ext/common/Utils/VariantMap.h +51 -2
- data/ext/common/Utils/jsoncpp.cpp +1 -1
- data/ext/common/agents/Base.cpp +147 -11
- data/ext/common/agents/HelperAgent/AgentOptions.h +14 -6
- data/ext/common/agents/HelperAgent/Main.cpp +79 -19
- data/ext/common/agents/HelperAgent/RequestHandler.h +36 -16
- data/ext/common/agents/LoggingAgent/LoggingServer.h +3 -5
- data/ext/common/agents/LoggingAgent/Main.cpp +2 -4
- data/ext/common/agents/LoggingAgent/RemoteSender.h +18 -24
- data/ext/common/agents/SpawnPreparer.cpp +7 -0
- data/ext/common/agents/Watchdog/Main.cpp +96 -38
- data/ext/nginx/Configuration.c +26 -22
- data/ext/nginx/Configuration.h +4 -2
- data/ext/nginx/ContentHandler.c +23 -52
- data/ext/nginx/ContentHandler.h +5 -11
- data/ext/nginx/config +10 -3
- data/ext/nginx/ngx_http_passenger_module.c +21 -6
- data/ext/nginx/ngx_http_passenger_module.h +4 -1
- data/ext/oxt/dynamic_thread_group.hpp +9 -1
- data/ext/oxt/system_calls.cpp +2 -2
- data/ext/ruby/extconf.rb +2 -1
- data/helper-scripts/backtrace-sanitizer.rb +2 -0
- data/helper-scripts/wsgi-loader.py +54 -21
- data/lib/phusion_passenger.rb +5 -3
- data/lib/phusion_passenger/abstract_installer.rb +18 -41
- data/lib/phusion_passenger/admin_tools/memory_stats.rb +2 -2
- data/lib/phusion_passenger/admin_tools/server_instance.rb +2 -2
- data/lib/phusion_passenger/common_library.rb +23 -3
- data/lib/phusion_passenger/debug_logging.rb +10 -3
- data/lib/phusion_passenger/packaging.rb +1 -0
- data/lib/phusion_passenger/platform_info.rb +113 -115
- data/lib/phusion_passenger/platform_info/compiler.rb +224 -134
- data/lib/phusion_passenger/platform_info/cxx_portability.rb +143 -0
- data/lib/phusion_passenger/platform_info/depcheck.rb +371 -0
- data/lib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +124 -0
- data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +97 -0
- data/lib/phusion_passenger/platform_info/depcheck_specs/gems.rb +39 -0
- data/lib/phusion_passenger/platform_info/depcheck_specs/libs.rb +118 -0
- data/lib/phusion_passenger/platform_info/depcheck_specs/ruby.rb +137 -0
- data/lib/phusion_passenger/platform_info/depcheck_specs/utilities.rb +15 -0
- data/lib/phusion_passenger/platform_info/operating_system.rb +6 -5
- data/lib/phusion_passenger/platform_info/ruby.rb +45 -34
- data/lib/phusion_passenger/request_handler.rb +35 -22
- data/lib/phusion_passenger/request_handler/thread_handler.rb +5 -6
- data/lib/phusion_passenger/ruby_core_enhancements.rb +7 -1
- data/lib/phusion_passenger/standalone/runtime_installer.rb +43 -34
- data/lib/phusion_passenger/utils/robust_interruption.rb +34 -18
- data/passenger.gemspec +25 -0
- data/resources/templates/standalone/config.erb +3 -1
- data/test/config.json.travis +2 -2
- data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +37 -5
- data/test/cxx/ApplicationPool2/PoolTest.cpp +143 -50
- data/test/cxx/ApplicationPool2/ProcessTest.cpp +8 -0
- data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +28 -17
- data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +31 -26
- data/test/cxx/RequestHandlerTest.cpp +17 -1
- data/test/cxx/UtilsTest.cpp +84 -10
- data/test/integration_tests/apache2_tests.rb +49 -163
- data/test/integration_tests/hello_world_wsgi_spec.rb +2 -2
- data/test/integration_tests/mycook_spec.rb +1 -1
- data/test/integration_tests/nginx_tests.rb +37 -19
- data/test/ruby/request_handler_spec.rb +1 -0
- data/test/ruby/spec_helper.rb +52 -1
- data/test/stub/nginx/nginx.conf.erb +2 -0
- data/test/stub/rack/start.rb +5 -0
- data/test/stub/rails3.0/Gemfile.lock +30 -30
- data/test/stub/rails3.1/Gemfile +1 -1
- data/test/stub/rails3.1/Gemfile.lock +3 -3
- data/test/stub/rails3.2/Gemfile +1 -1
- data/test/stub/rails3.2/Gemfile.lock +4 -4
- data/test/stub/rails_apps/2.3/mycook/app/controllers/welcome_controller.rb +1 -1
- data/test/stub/rails_apps/2.3/mycook/app/helpers/recipes_helper.rb +2 -0
- data/test/stub/rails_apps/2.3/mycook/app/helpers/test_helper.rb +2 -0
- data/test/stub/rails_apps/2.3/mycook/app/helpers/uploads_helper.rb +2 -0
- data/test/stub/rails_apps/2.3/mycook/app/helpers/welcome_helper.rb +2 -0
- data/test/support/nginx_controller.rb +2 -1
- metadata +160 -156
- data/build/gempackagetask.rb +0 -99
- data/build/packagetask.rb +0 -186
- data/ext/common/StringListCreator.h +0 -83
- data/lib/phusion_passenger/dependencies.rb +0 -657
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2011 Phusion
|
3
|
+
* Copyright (c) 2011-2013 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -30,6 +30,7 @@
|
|
30
30
|
#include <utility>
|
31
31
|
|
32
32
|
#include <StaticString.h>
|
33
|
+
#include <Utils/HashMap.h>
|
33
34
|
|
34
35
|
namespace Passenger {
|
35
36
|
|
@@ -53,7 +54,7 @@ private:
|
|
53
54
|
pair<StaticString, T> thePair;
|
54
55
|
};
|
55
56
|
|
56
|
-
typedef
|
57
|
+
typedef HashMap<StaticString, Entry, StaticString::Hash> InternalMap;
|
57
58
|
typedef typename InternalMap::iterator InternalIterator;
|
58
59
|
typedef typename InternalMap::const_iterator InternalConstIterator;
|
59
60
|
typedef typename InternalMap::value_type ValueType;
|
@@ -160,6 +161,15 @@ public:
|
|
160
161
|
return it->second.thePair.second;
|
161
162
|
}
|
162
163
|
}
|
164
|
+
|
165
|
+
T get(const StaticString &key, const T &defaultValue) const {
|
166
|
+
InternalConstIterator it = store.find(key);
|
167
|
+
if (it == store.end()) {
|
168
|
+
return defaultValue;
|
169
|
+
} else {
|
170
|
+
return it->second.thePair.second;
|
171
|
+
}
|
172
|
+
}
|
163
173
|
|
164
174
|
bool set(const StaticString &key, const T &value) {
|
165
175
|
pair<InternalIterator, bool> result = store.insert(make_pair(key, Entry()));
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2010 Phusion
|
3
|
+
* Copyright (c) 2010-2013 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -168,37 +168,86 @@ public:
|
|
168
168
|
store[name] = value;
|
169
169
|
return *this;
|
170
170
|
}
|
171
|
+
|
172
|
+
VariantMap &setDefault(const string &name, const string &value) {
|
173
|
+
if (store.find(name) == store.end()) {
|
174
|
+
store[name] = value;
|
175
|
+
}
|
176
|
+
return *this;
|
177
|
+
}
|
171
178
|
|
172
179
|
VariantMap &setInt(const string &name, int value) {
|
173
180
|
store[name] = toString(value);
|
174
181
|
return *this;
|
175
182
|
}
|
183
|
+
|
184
|
+
VariantMap &setDefaultInt(const string &name, int value) {
|
185
|
+
if (store.find(name) == store.end()) {
|
186
|
+
store[name] = toString(value);
|
187
|
+
}
|
188
|
+
return *this;
|
189
|
+
}
|
176
190
|
|
177
191
|
VariantMap &setULL(const string &name, unsigned long long value) {
|
178
192
|
store[name] = toString(value);
|
179
193
|
return *this;
|
180
194
|
}
|
195
|
+
|
196
|
+
VariantMap &setDefaultULL(const string &name, unsigned long long value) {
|
197
|
+
if (store.find(name) == store.end()) {
|
198
|
+
store[name] = toString(value);
|
199
|
+
}
|
200
|
+
return *this;
|
201
|
+
}
|
181
202
|
|
182
203
|
VariantMap &setPid(const string &name, pid_t value) {
|
183
204
|
store[name] = toString((unsigned long long) value);
|
184
205
|
return *this;
|
185
206
|
}
|
207
|
+
|
208
|
+
VariantMap &setDefaultPid(const string &name, pid_t value) {
|
209
|
+
if (store.find(name) == store.end()) {
|
210
|
+
store[name] = toString((unsigned long long) value);
|
211
|
+
}
|
212
|
+
return *this;
|
213
|
+
}
|
186
214
|
|
187
215
|
VariantMap &setUid(const string &name, uid_t value) {
|
188
216
|
store[name] = toString((long long) value);
|
189
217
|
return *this;
|
190
218
|
}
|
219
|
+
|
220
|
+
VariantMap &setDefaultUid(const string &name, uid_t value) {
|
221
|
+
if (store.find(name) == store.end()) {
|
222
|
+
store[name] = toString((unsigned long long) value);
|
223
|
+
}
|
224
|
+
return *this;
|
225
|
+
}
|
191
226
|
|
192
227
|
VariantMap &setGid(const string &name, gid_t value) {
|
193
228
|
store[name] = toString((long long) value);
|
194
229
|
return *this;
|
195
230
|
}
|
231
|
+
|
232
|
+
VariantMap &setDefaultGid(const string &name, gid_t value) {
|
233
|
+
if (store.find(name) == store.end()) {
|
234
|
+
store[name] = toString((unsigned long long) value);
|
235
|
+
}
|
236
|
+
return *this;
|
237
|
+
}
|
196
238
|
|
197
239
|
VariantMap &setBool(const string &name, bool value) {
|
198
240
|
store[name] = value ? "true" : "false";
|
199
241
|
return *this;
|
200
242
|
}
|
201
|
-
|
243
|
+
|
244
|
+
VariantMap &setDefaultBool(const string &name, bool value) {
|
245
|
+
if (store.find(name) == store.end()) {
|
246
|
+
store[name] = value ? "true" : "false";
|
247
|
+
}
|
248
|
+
return *this;
|
249
|
+
}
|
250
|
+
|
202
251
|
const string &get(const string &name, bool required = true) const {
|
203
252
|
map<string, string>::const_iterator it = store.find(name);
|
204
253
|
if (it == store.end()) {
|
@@ -3461,7 +3461,7 @@ std::string valueToString( double value )
|
|
3461
3461
|
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning.
|
3462
3462
|
sprintf_s(buffer, sizeof(buffer), "%#.16g", value);
|
3463
3463
|
#else
|
3464
|
-
|
3464
|
+
snprintf(buffer, sizeof(buffer), "%#.16g", value);
|
3465
3465
|
#endif
|
3466
3466
|
char* ch = buffer + strlen(buffer) - 1;
|
3467
3467
|
if (*ch != '0') return buffer; // nothing to truncate, so save time
|
data/ext/common/agents/Base.cpp
CHANGED
@@ -33,11 +33,13 @@
|
|
33
33
|
#include <sys/select.h>
|
34
34
|
#ifdef __linux__
|
35
35
|
#include <sys/syscall.h>
|
36
|
+
#include <features.h>
|
36
37
|
#endif
|
37
38
|
#include <cstdio>
|
38
39
|
#include <cstdlib>
|
39
40
|
#include <cstring>
|
40
41
|
#include <cerrno>
|
42
|
+
#include <cassert>
|
41
43
|
#include <fcntl.h>
|
42
44
|
#include <poll.h>
|
43
45
|
#include <unistd.h>
|
@@ -96,7 +98,8 @@ static bool stopOnAbort = false;
|
|
96
98
|
static char *alternativeStack;
|
97
99
|
static unsigned int alternativeStackSize;
|
98
100
|
|
99
|
-
static unsigned int
|
101
|
+
static volatile unsigned int abortHandlerCalled = 0;
|
102
|
+
static unsigned int randomSeed = 0;
|
100
103
|
static const char *argv0 = NULL;
|
101
104
|
static const char *backtraceSanitizerPath = NULL;
|
102
105
|
static bool backtraceSanitizerUseShell = false;
|
@@ -104,6 +107,14 @@ static bool backtraceSanitizerPassProgramInfo = true;
|
|
104
107
|
static DiagnosticsDumper customDiagnosticsDumper = NULL;
|
105
108
|
static void *customDiagnosticsDumperUserData;
|
106
109
|
|
110
|
+
// If assert() failed, its information is stored here.
|
111
|
+
static struct {
|
112
|
+
const char *filename;
|
113
|
+
const char *function; // May be NULL.
|
114
|
+
const char *expression;
|
115
|
+
unsigned int line;
|
116
|
+
} lastAssertionFailure;
|
117
|
+
|
107
118
|
|
108
119
|
static void
|
109
120
|
ignoreSigpipe() {
|
@@ -254,6 +265,9 @@ appendSignalName(char *buf, int signo) {
|
|
254
265
|
case SIGFPE:
|
255
266
|
buf = appendText(buf, "SIGFPE");
|
256
267
|
break;
|
268
|
+
case SIGILL:
|
269
|
+
buf = appendText(buf, "SIGILL");
|
270
|
+
break;
|
257
271
|
default:
|
258
272
|
return appendULL(buf, (unsigned long long) signo);
|
259
273
|
}
|
@@ -454,10 +468,12 @@ dumpWithCrashWatch(AbortHandlerState &state) {
|
|
454
468
|
if (pipe(p) == -1) {
|
455
469
|
int e = errno;
|
456
470
|
end = state.messageBuf;
|
457
|
-
end = appendText(end, "Could not dump diagnostics: pipe() failed with errno=");
|
471
|
+
end = appendText(end, "Could not dump diagnostics through backtrace sanitizer: pipe() failed with errno=");
|
458
472
|
end = appendULL(end, e);
|
459
473
|
end = appendText(end, "\n");
|
474
|
+
end = appendText(end, "Falling back to writing to stderr directly...\n");
|
460
475
|
write(STDERR_FILENO, state.messageBuf, end - state.messageBuf);
|
476
|
+
backtrace_symbols_fd(backtraceStore, frames, STDERR_FILENO);
|
461
477
|
return;
|
462
478
|
}
|
463
479
|
|
@@ -505,12 +521,29 @@ dumpWithCrashWatch(AbortHandlerState &state) {
|
|
505
521
|
} else if (pid == -1) {
|
506
522
|
close(p[0]);
|
507
523
|
close(p[1]);
|
524
|
+
int e = errno;
|
525
|
+
end = state.messageBuf;
|
526
|
+
end = appendText(end, "Could not dump diagnostics through backtrace sanitizer: fork() failed with errno=");
|
527
|
+
end = appendULL(end, e);
|
528
|
+
end = appendText(end, "\n");
|
529
|
+
end = appendText(end, "Falling back to writing to stderr directly...\n");
|
530
|
+
write(STDERR_FILENO, state.messageBuf, end - state.messageBuf);
|
531
|
+
backtrace_symbols_fd(backtraceStore, frames, STDERR_FILENO);
|
508
532
|
|
509
533
|
} else {
|
534
|
+
int status = -1;
|
535
|
+
|
510
536
|
close(p[0]);
|
511
537
|
backtrace_symbols_fd(backtraceStore, frames, p[1]);
|
512
538
|
close(p[1]);
|
513
|
-
waitpid(pid,
|
539
|
+
if (waitpid(pid, &status, 0) == -1 || status != 0) {
|
540
|
+
end = state.messageBuf;
|
541
|
+
end = appendText(end, "ERROR: cannot execute '");
|
542
|
+
end = appendText(end, backtraceSanitizerPath);
|
543
|
+
end = appendText(end, "' for sanitizing the backtrace, writing to stderr directly...\n");
|
544
|
+
write(STDERR_FILENO, state.messageBuf, end - state.messageBuf);
|
545
|
+
backtrace_symbols_fd(backtraceStore, frames, STDERR_FILENO);
|
546
|
+
}
|
514
547
|
}
|
515
548
|
|
516
549
|
} else {
|
@@ -524,12 +557,15 @@ runCustomDiagnosticsDumper(AbortHandlerState &state, void *userData) {
|
|
524
557
|
customDiagnosticsDumper(customDiagnosticsDumperUserData);
|
525
558
|
}
|
526
559
|
|
560
|
+
// This function is performed in a child process.
|
527
561
|
static void
|
528
562
|
dumpDiagnostics(AbortHandlerState &state) {
|
529
563
|
char *messageBuf = state.messageBuf;
|
564
|
+
char *end;
|
565
|
+
pid_t pid;
|
530
566
|
|
531
|
-
// Dump human-readable time string.
|
532
|
-
|
567
|
+
// Dump human-readable time string and string.
|
568
|
+
pid = asyncFork();
|
533
569
|
if (pid == 0) {
|
534
570
|
execlp("date", "date", (const char * const) 0);
|
535
571
|
_exit(1);
|
@@ -539,10 +575,45 @@ dumpDiagnostics(AbortHandlerState &state) {
|
|
539
575
|
waitpid(pid, NULL, 0);
|
540
576
|
}
|
541
577
|
|
578
|
+
// Dump system uname.
|
579
|
+
pid = asyncFork();
|
580
|
+
if (pid == 0) {
|
581
|
+
execlp("uname", "uname", "-mprsv", (const char * const) 0);
|
582
|
+
_exit(1);
|
583
|
+
} else if (pid == -1) {
|
584
|
+
safePrintErr("ERROR: Could not fork a process to dump the uname!\n");
|
585
|
+
} else {
|
586
|
+
waitpid(pid, NULL, 0);
|
587
|
+
}
|
588
|
+
|
589
|
+
end = messageBuf;
|
590
|
+
end = appendText(end, state.messagePrefix);
|
591
|
+
end = appendText(end, " ] Phusion Passenger version: " PASSENGER_VERSION "\n");
|
592
|
+
write(STDERR_FILENO, messageBuf, end - messageBuf);
|
593
|
+
|
594
|
+
if (lastAssertionFailure.filename != NULL) {
|
595
|
+
end = messageBuf;
|
596
|
+
end = appendText(end, state.messagePrefix);
|
597
|
+
end = appendText(end, " ] Last assertion failure: (");
|
598
|
+
end = appendText(end, lastAssertionFailure.expression);
|
599
|
+
end = appendText(end, "), ");
|
600
|
+
if (lastAssertionFailure.function != NULL) {
|
601
|
+
end = appendText(end, "function ");
|
602
|
+
end = appendText(end, lastAssertionFailure.function);
|
603
|
+
end = appendText(end, ", ");
|
604
|
+
}
|
605
|
+
end = appendText(end, "file ");
|
606
|
+
end = appendText(end, lastAssertionFailure.filename);
|
607
|
+
end = appendText(end, ", line ");
|
608
|
+
end = appendULL(end, lastAssertionFailure.line);
|
609
|
+
end = appendText(end, ".\n");
|
610
|
+
write(STDERR_FILENO, messageBuf, end - messageBuf);
|
611
|
+
}
|
612
|
+
|
542
613
|
// It is important that writing the message and the backtrace are two
|
543
614
|
// seperate operations because it's not entirely clear whether the
|
544
615
|
// latter is async signal safe and thus can crash.
|
545
|
-
|
616
|
+
end = messageBuf;
|
546
617
|
end = appendText(end, state.messagePrefix);
|
547
618
|
#ifdef LIBC_HAS_BACKTRACE_FUNC
|
548
619
|
end = appendText(end, " ] libc backtrace available!\n");
|
@@ -648,6 +719,40 @@ abortHandler(int signo, siginfo_t *info, void *ctx) {
|
|
648
719
|
time_t t = time(NULL);
|
649
720
|
char crashLogFile[256];
|
650
721
|
|
722
|
+
abortHandlerCalled++;
|
723
|
+
if (abortHandlerCalled > 1) {
|
724
|
+
// The abort handler itself crashed!
|
725
|
+
char *end = state.messageBuf;
|
726
|
+
end = appendText(end, "[ origpid=");
|
727
|
+
end = appendULL(end, (unsigned long long) state.pid);
|
728
|
+
end = appendText(end, ", pid=");
|
729
|
+
end = appendULL(end, (unsigned long long) getpid());
|
730
|
+
end = appendText(end, ", timestamp=");
|
731
|
+
end = appendULL(end, (unsigned long long) t);
|
732
|
+
if (abortHandlerCalled == 2) {
|
733
|
+
// This is the first time it crashed.
|
734
|
+
end = appendText(end, " ] Abort handler crashed! signo=");
|
735
|
+
end = appendSignalName(end, state.signo);
|
736
|
+
end = appendText(end, ", reason=");
|
737
|
+
end = appendSignalReason(end, state.info);
|
738
|
+
end = appendText(end, "\n");
|
739
|
+
write(STDERR_FILENO, state.messageBuf, end - state.messageBuf);
|
740
|
+
// Run default signal handler.
|
741
|
+
raise(signo);
|
742
|
+
} else {
|
743
|
+
// This is the second time it crashed, meaning it failed to
|
744
|
+
// invoke the default signal handler to abort the process!
|
745
|
+
end = appendText(end, " ] Abort handler crashed again! Force exiting this time. signo=");
|
746
|
+
end = appendSignalName(end, state.signo);
|
747
|
+
end = appendText(end, ", reason=");
|
748
|
+
end = appendSignalReason(end, state.info);
|
749
|
+
end = appendText(end, "\n");
|
750
|
+
write(STDERR_FILENO, state.messageBuf, end - state.messageBuf);
|
751
|
+
_exit(1);
|
752
|
+
}
|
753
|
+
return;
|
754
|
+
}
|
755
|
+
|
651
756
|
/* We want to dump the entire crash log to both stderr and a log file.
|
652
757
|
* We use 'tee' for this.
|
653
758
|
*/
|
@@ -739,6 +844,11 @@ abortHandler(int signo, siginfo_t *info, void *ctx) {
|
|
739
844
|
|
740
845
|
child = asyncFork();
|
741
846
|
if (child == 0) {
|
847
|
+
// OS X: for some reason the SIGPIPE handler may be reset to default after forking.
|
848
|
+
// Later in this program we're going to pipe backtrace_symbols_fd() into the backtrace
|
849
|
+
// sanitizer, which may fail, and we don't want the diagnostics process to crash
|
850
|
+
// with SIGPIPE as a result, so we ignore SIGPIPE again.
|
851
|
+
ignoreSigpipe();
|
742
852
|
dumpDiagnostics(state);
|
743
853
|
// The child process may or may or may not resume the original process.
|
744
854
|
// We do it ourselves just to be sure.
|
@@ -778,7 +888,27 @@ abortHandler(int signo, siginfo_t *info, void *ctx) {
|
|
778
888
|
raise(signo);
|
779
889
|
}
|
780
890
|
|
781
|
-
|
891
|
+
/*
|
892
|
+
* Override assert() to add more features and to fix bugs. We save the information
|
893
|
+
* of the last assertion failure in a global variable so that we can print it
|
894
|
+
* to the crash diagnostics report.
|
895
|
+
*/
|
896
|
+
#if defined(__GLIBC__)
|
897
|
+
extern "C" __attribute__ ((__noreturn__))
|
898
|
+
void
|
899
|
+
__assert_fail(__const char *__assertion, __const char *__file,
|
900
|
+
unsigned int __line, __const char *__function)
|
901
|
+
{
|
902
|
+
lastAssertionFailure.filename = __file;
|
903
|
+
lastAssertionFailure.line = __line;
|
904
|
+
lastAssertionFailure.function = __function;
|
905
|
+
lastAssertionFailure.expression = __assertion;
|
906
|
+
fprintf(stderr, "Assertion failed! %s:%u: %s: %s\n", __file, __line, __function, __assertion);
|
907
|
+
fflush(stderr);
|
908
|
+
abort();
|
909
|
+
}
|
910
|
+
|
911
|
+
#elif defined(__APPLE__)
|
782
912
|
/* On OS X, raise() and abort() unfortunately send SIGABRT to the main thread,
|
783
913
|
* causing the original backtrace to be lost in the signal handler.
|
784
914
|
* We work around this for anything in the same linkage unit by just definin
|
@@ -787,13 +917,17 @@ abortHandler(int signo, siginfo_t *info, void *ctx) {
|
|
787
917
|
|
788
918
|
#include <pthread.h>
|
789
919
|
|
790
|
-
|
920
|
+
extern "C" int
|
791
921
|
raise(int sig) {
|
792
922
|
return pthread_kill(pthread_self(), sig);
|
793
923
|
}
|
794
924
|
|
795
|
-
void
|
925
|
+
extern "C" void
|
796
926
|
__assert_rtn(const char *func, const char *file, int line, const char *expr) {
|
927
|
+
lastAssertionFailure.filename = file;
|
928
|
+
lastAssertionFailure.line = line;
|
929
|
+
lastAssertionFailure.function = func;
|
930
|
+
lastAssertionFailure.expression = expr;
|
797
931
|
if (func) {
|
798
932
|
fprintf(stderr, "Assertion failed: (%s), function %s, file %s, line %d.\n",
|
799
933
|
expr, func, file, line);
|
@@ -801,10 +935,11 @@ abortHandler(int signo, siginfo_t *info, void *ctx) {
|
|
801
935
|
fprintf(stderr, "Assertion failed: (%s), file %s, line %d.\n",
|
802
936
|
expr, file, line);
|
803
937
|
}
|
938
|
+
fflush(stderr);
|
804
939
|
abort();
|
805
940
|
}
|
806
941
|
|
807
|
-
void
|
942
|
+
extern "C" void
|
808
943
|
abort() {
|
809
944
|
sigset_t set;
|
810
945
|
sigemptyset(&set);
|
@@ -1254,7 +1389,8 @@ initializeAgent(int argc, char *argv[], const char *processName) {
|
|
1254
1389
|
backtraceSanitizerPassProgramInfo = false;
|
1255
1390
|
}
|
1256
1391
|
|
1257
|
-
|
1392
|
+
options.setDefaultInt("log_level", DEFAULT_LOG_LEVEL);
|
1393
|
+
setLogLevel(options.getInt("log_level"));
|
1258
1394
|
if (!options.get("debug_log_file", false).empty()) {
|
1259
1395
|
if (strcmp(processName, "PassengerWatchdog") == 0) {
|
1260
1396
|
/* Have the watchdog set STDOUT and STDERR to the debug
|
@@ -53,25 +53,33 @@ struct AgentOptions {
|
|
53
53
|
string loggingAgentPassword;
|
54
54
|
string prestartUrls;
|
55
55
|
|
56
|
+
string requestSocketLink;
|
57
|
+
|
56
58
|
AgentOptions() { }
|
57
59
|
|
58
60
|
AgentOptions(const VariantMap &options) {
|
59
|
-
|
60
|
-
|
61
|
+
// Required options for which a default is already set by the Watchdog.
|
62
|
+
passengerRoot = options.get("passenger_root");
|
63
|
+
tempDir = options.get("temp_dir");
|
61
64
|
userSwitching = options.getBool("user_switching");
|
65
|
+
rubyCommand = options.get("ruby");
|
62
66
|
defaultUser = options.get("default_user");
|
63
67
|
defaultGroup = options.get("default_group");
|
64
|
-
passengerRoot = options.get("passenger_root");
|
65
|
-
rubyCommand = options.get("ruby");
|
66
|
-
generationNumber = options.getInt("generation_number");
|
67
68
|
maxPoolSize = options.getInt("max_pool_size");
|
68
69
|
maxInstancesPerApp = options.getInt("max_instances_per_app");
|
69
70
|
poolIdleTime = options.getInt("pool_idle_time");
|
71
|
+
|
72
|
+
// Required options only set by the Watchdog.
|
73
|
+
webServerPid = options.getPid("web_server_pid");
|
74
|
+
generationNumber = options.getInt("generation_number");
|
70
75
|
requestSocketPassword = Base64::decode(options.get("request_socket_password"));
|
71
76
|
messageSocketPassword = Base64::decode(options.get("message_socket_password"));
|
72
77
|
loggingAgentAddress = options.get("logging_agent_address");
|
73
78
|
loggingAgentPassword = options.get("logging_agent_password");
|
74
|
-
|
79
|
+
|
80
|
+
// Optional options.
|
81
|
+
prestartUrls = options.get("prestart_urls", false, "");
|
82
|
+
requestSocketLink = options.get("request_socket_link", false);
|
75
83
|
}
|
76
84
|
};
|
77
85
|
|