passenger 4.0.0.rc4 → 4.0.0.rc6
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.tar.gz.asc +12 -0
- data/.travis.yml +4 -4
- data/NEWS +46 -0
- data/bin/passenger-config +31 -1
- data/bin/passenger-install-apache2-module +1 -1
- data/bin/passenger-install-nginx-module +1 -0
- data/build/common_library.rb +4 -0
- data/build/cplusplus_support.rb +27 -6
- data/build/cxx_tests.rb +1 -1
- data/build/misc.rb +28 -6
- data/build/packaging.rb +72 -65
- data/build/test_basics.rb +1 -1
- data/dev/googlecode_upload.py +265 -0
- data/dev/run_travis.sh +9 -0
- data/doc/Users guide Apache.html +376 -193
- data/doc/Users guide Apache.idmap.txt +80 -62
- data/doc/Users guide Apache.txt +61 -35
- data/doc/Users guide Nginx.html +278 -83
- data/doc/Users guide Nginx.idmap.txt +26 -10
- data/doc/Users guide Nginx.txt +59 -31
- data/doc/Users guide Standalone.html +1 -1
- data/doc/users_guide_snippets/installation.txt +121 -11
- data/doc/users_guide_snippets/rvm_helper_tool.txt +56 -0
- data/ext/apache2/Bucket.cpp +1 -1
- data/ext/apache2/Configuration.cpp +7 -1
- data/ext/apache2/Configuration.hpp +4 -0
- data/ext/apache2/Hooks.cpp +2 -2
- data/ext/common/AgentsStarter.cpp +2 -2
- data/ext/common/AgentsStarter.h +1 -1
- data/ext/common/AgentsStarter.hpp +2 -2
- data/ext/common/ApplicationPool2/DirectSpawner.h +4 -8
- data/ext/common/ApplicationPool2/Group.h +17 -11
- data/ext/common/ApplicationPool2/Implementation.cpp +39 -11
- data/ext/common/ApplicationPool2/Pool.h +23 -4
- data/ext/common/ApplicationPool2/Process.h +30 -11
- data/ext/common/ApplicationPool2/SmartSpawner.h +3 -1
- data/ext/common/Constants.h +1 -1
- data/ext/common/EventedBufferedInput.h +4 -0
- data/ext/common/Utils.cpp +21 -3
- data/ext/common/Utils.h +8 -1
- data/ext/common/Utils/HttpHeaderBufferer.h +1 -1
- data/ext/common/Utils/IOUtils.cpp +5 -4
- data/ext/common/Utils/IOUtils.h +32 -14
- data/ext/common/Utils/MessagePassing.h +2 -2
- data/ext/common/Utils/ProcessMetricsCollector.h +47 -15
- data/ext/common/Utils/ScopeGuard.h +20 -3
- data/ext/common/Utils/StrIntUtils.h +14 -5
- data/ext/common/agents/Base.cpp +161 -50
- data/ext/common/agents/HelperAgent/AgentOptions.h +2 -2
- data/ext/common/agents/HelperAgent/Main.cpp +1 -0
- data/ext/common/agents/HelperAgent/RequestHandler.h +166 -52
- data/ext/common/agents/LoggingAgent/Main.cpp +1 -1
- data/ext/common/agents/Watchdog/Main.cpp +2 -2
- data/ext/nginx/Configuration.c +31 -4
- data/ext/nginx/Configuration.h +1 -0
- data/ext/nginx/ContentHandler.c +148 -34
- data/ext/nginx/ngx_http_passenger_module.c +4 -1
- data/ext/oxt/detail/spin_lock_pthreads.hpp +4 -4
- data/ext/oxt/macros.hpp +30 -8
- data/lib/phusion_passenger.rb +2 -2
- data/lib/phusion_passenger/classic_rails/thread_handler_extension.rb +1 -1
- data/lib/phusion_passenger/native_support.rb +19 -1
- data/lib/phusion_passenger/platform_info/compiler.rb +6 -0
- data/lib/phusion_passenger/platform_info/ruby.rb +54 -5
- data/lib/phusion_passenger/preloader_shared_helpers.rb +8 -1
- data/lib/phusion_passenger/rack/out_of_band_gc.rb +3 -1
- data/lib/phusion_passenger/rack/thread_handler_extension.rb +32 -5
- data/lib/phusion_passenger/request_handler/thread_handler.rb +28 -8
- data/lib/phusion_passenger/ruby_core_enhancements.rb +9 -1
- data/lib/phusion_passenger/standalone/runtime_installer.rb +1 -0
- data/lib/phusion_passenger/utils/unseekable_socket.rb +50 -5
- data/passenger.gemspec +1 -1
- data/resources/templates/apache2/config_snippets.txt.erb +1 -1
- data/test/cxx/ApplicationPool2/PoolTest.cpp +4 -9
- data/test/cxx/RequestHandlerTest.cpp +5 -5
- data/test/ruby/classic_rails/loader_spec.rb +1 -1
- data/test/ruby/classic_rails/preloader_spec.rb +1 -1
- data/test/ruby/request_handler_spec.rb +207 -1
- data/test/ruby/shared/loader_sharedspec.rb +1 -0
- data/test/ruby/spec_helper.rb +11 -1
- data/test/stub/apache2/httpd.conf.erb +1 -1
- metadata +5 -3
- metadata.gz.asc +12 -0
@@ -27,11 +27,14 @@
|
|
27
27
|
|
28
28
|
#include <boost/noncopyable.hpp>
|
29
29
|
#include <boost/function.hpp>
|
30
|
+
#include <boost/thread.hpp>
|
31
|
+
#include <oxt/system_calls.hpp>
|
30
32
|
#include <cstdio>
|
31
33
|
|
32
34
|
namespace Passenger {
|
33
35
|
|
34
36
|
using namespace boost;
|
37
|
+
using namespace oxt;
|
35
38
|
|
36
39
|
|
37
40
|
#ifndef _PASSENGER_SAFELY_CLOSE_DEFINED_
|
@@ -48,17 +51,25 @@ using namespace boost;
|
|
48
51
|
class ScopeGuard: public noncopyable {
|
49
52
|
private:
|
50
53
|
function<void ()> func;
|
54
|
+
bool interruptable;
|
51
55
|
|
52
56
|
public:
|
53
57
|
ScopeGuard() { }
|
54
58
|
|
55
|
-
ScopeGuard(const function<void ()> &func) {
|
59
|
+
ScopeGuard(const function<void ()> &func, bool interruptable = false) {
|
56
60
|
this->func = func;
|
61
|
+
this->interruptable = interruptable;
|
57
62
|
}
|
58
63
|
|
59
64
|
~ScopeGuard() {
|
60
65
|
if (func) {
|
61
|
-
|
66
|
+
if (interruptable) {
|
67
|
+
func();
|
68
|
+
} else {
|
69
|
+
this_thread::disable_interruption di;
|
70
|
+
this_thread::disable_syscall_interruption dsi;
|
71
|
+
func();
|
72
|
+
}
|
62
73
|
}
|
63
74
|
}
|
64
75
|
|
@@ -69,7 +80,13 @@ public:
|
|
69
80
|
void runNow() {
|
70
81
|
function<void ()> oldFunc = func;
|
71
82
|
func = function<void()>();
|
72
|
-
|
83
|
+
if (interruptable) {
|
84
|
+
oldFunc();
|
85
|
+
} else {
|
86
|
+
this_thread::disable_interruption di;
|
87
|
+
this_thread::disable_syscall_interruption dsi;
|
88
|
+
oldFunc();
|
89
|
+
}
|
73
90
|
}
|
74
91
|
};
|
75
92
|
|
@@ -30,6 +30,7 @@
|
|
30
30
|
#include <sstream>
|
31
31
|
#include <cstddef>
|
32
32
|
#include <ctime>
|
33
|
+
#include <oxt/macros.hpp>
|
33
34
|
#include <StaticString.h>
|
34
35
|
|
35
36
|
namespace Passenger {
|
@@ -74,8 +75,12 @@ bool startsWith(const StaticString &str, const StaticString &substr);
|
|
74
75
|
* @param sep The separator to use.
|
75
76
|
* @param output The vector to write the output to.
|
76
77
|
*/
|
77
|
-
void split(const StaticString &
|
78
|
-
|
78
|
+
void split(const StaticString & restrict_ref str,
|
79
|
+
char sep,
|
80
|
+
vector<string> & restrict_ref output);
|
81
|
+
void split(const StaticString & restrict_ref str,
|
82
|
+
char sep,
|
83
|
+
vector<StaticString> & restrict_ref output);
|
79
84
|
|
80
85
|
/**
|
81
86
|
* Split the given string using the given separator. Includes the
|
@@ -85,8 +90,12 @@ void split(const StaticString &str, char sep, vector<StaticString> &output);
|
|
85
90
|
* @param sep The separator to use.
|
86
91
|
* @param output The vector to write the output to.
|
87
92
|
*/
|
88
|
-
void splitIncludeSep(const StaticString &
|
89
|
-
|
93
|
+
void splitIncludeSep(const StaticString & restrict_ref str,
|
94
|
+
char sep,
|
95
|
+
vector<string> & restrict_ref output);
|
96
|
+
void splitIncludeSep(const StaticString & restrict_ref str,
|
97
|
+
char sep,
|
98
|
+
vector<StaticString> & restrict_ref output);
|
90
99
|
|
91
100
|
/**
|
92
101
|
* Look for 'toFind' inside 'str', replace it with 'replaceWith' and return the result.
|
@@ -146,7 +155,7 @@ string toHex(const StaticString &data);
|
|
146
155
|
* Convert the given binary data to hexadecimal. This form accepts an
|
147
156
|
* output buffer which must be at least <tt>data.size() * 2</tt> bytes large.
|
148
157
|
*/
|
149
|
-
void toHex(const StaticString &data, char *output, bool upperCase = false);
|
158
|
+
void toHex(const StaticString & restrict_ref data, char * restrict output, bool upperCase = false);
|
150
159
|
|
151
160
|
/**
|
152
161
|
* Convert the given integer to some other radix, placing
|
data/ext/common/agents/Base.cpp
CHANGED
@@ -60,6 +60,7 @@
|
|
60
60
|
#include <Constants.h>
|
61
61
|
#include <Exceptions.h>
|
62
62
|
#include <Logging.h>
|
63
|
+
#include <ResourceLocator.h>
|
63
64
|
#include <Utils.h>
|
64
65
|
#include <Utils/StrIntUtils.h>
|
65
66
|
#ifdef __linux__
|
@@ -101,12 +102,17 @@ static unsigned int alternativeStackSize;
|
|
101
102
|
static volatile unsigned int abortHandlerCalled = 0;
|
102
103
|
static unsigned int randomSeed = 0;
|
103
104
|
static const char *argv0 = NULL;
|
104
|
-
static const char *
|
105
|
-
static bool backtraceSanitizerUseShell = false;
|
105
|
+
static const char *backtraceSanitizerCommand = NULL;
|
106
106
|
static bool backtraceSanitizerPassProgramInfo = true;
|
107
107
|
static DiagnosticsDumper customDiagnosticsDumper = NULL;
|
108
108
|
static void *customDiagnosticsDumperUserData;
|
109
109
|
|
110
|
+
// We preallocate a few pipes during startup which we will close in the
|
111
|
+
// crash handler. This way we can be sure that when the crash handler
|
112
|
+
// calls pipe() it won't fail with "Too many files".
|
113
|
+
static int emergencyPipe1[2] = { -1, -1 };
|
114
|
+
static int emergencyPipe2[2] = { -1, -1 };
|
115
|
+
|
110
116
|
// If assert() failed, its information is stored here.
|
111
117
|
static struct {
|
112
118
|
const char *filename;
|
@@ -143,17 +149,6 @@ hasEnvOption(const char *name, bool defaultValue = false) {
|
|
143
149
|
}
|
144
150
|
}
|
145
151
|
|
146
|
-
// Async-signal safe way to fork().
|
147
|
-
// http://sourceware.org/bugzilla/show_bug.cgi?id=4737
|
148
|
-
static pid_t
|
149
|
-
asyncFork() {
|
150
|
-
#if defined(__linux__)
|
151
|
-
return (pid_t) syscall(SYS_fork);
|
152
|
-
#else
|
153
|
-
return fork();
|
154
|
-
#endif
|
155
|
-
}
|
156
|
-
|
157
152
|
// No idea whether strlen() is async signal safe, but let's not risk it
|
158
153
|
// and write our own version instead that's guaranteed to be safe.
|
159
154
|
static size_t
|
@@ -361,7 +356,7 @@ appendSignalReason(char *buf, siginfo_t *info) {
|
|
361
356
|
return buf;
|
362
357
|
}
|
363
358
|
|
364
|
-
static
|
359
|
+
static int
|
365
360
|
runInSubprocessWithTimeLimit(AbortHandlerState &state, Callback callback, void *userData, int timeLimit) {
|
366
361
|
char *end;
|
367
362
|
pid_t child;
|
@@ -370,11 +365,11 @@ runInSubprocessWithTimeLimit(AbortHandlerState &state, Callback callback, void *
|
|
370
365
|
if (pipe(p) == -1) {
|
371
366
|
e = errno;
|
372
367
|
end = state.messageBuf;
|
373
|
-
end = appendText(end, "Could not
|
368
|
+
end = appendText(end, "Could not create subprocess: pipe() failed with errno=");
|
374
369
|
end = appendULL(end, e);
|
375
370
|
end = appendText(end, "\n");
|
376
371
|
write(STDERR_FILENO, state.messageBuf, end - state.messageBuf);
|
377
|
-
return;
|
372
|
+
return -1;
|
378
373
|
}
|
379
374
|
|
380
375
|
child = asyncFork();
|
@@ -382,18 +377,21 @@ runInSubprocessWithTimeLimit(AbortHandlerState &state, Callback callback, void *
|
|
382
377
|
close(p[0]);
|
383
378
|
callback(state, userData);
|
384
379
|
_exit(0);
|
380
|
+
return -1;
|
385
381
|
|
386
382
|
} else if (child == -1) {
|
387
383
|
e = errno;
|
388
384
|
close(p[0]);
|
389
385
|
close(p[1]);
|
390
386
|
end = state.messageBuf;
|
391
|
-
end = appendText(end, "Could not
|
387
|
+
end = appendText(end, "Could not create subprocess: fork() failed with errno=");
|
392
388
|
end = appendULL(end, e);
|
393
389
|
end = appendText(end, "\n");
|
394
390
|
write(STDERR_FILENO, state.messageBuf, end - state.messageBuf);
|
391
|
+
return -1;
|
395
392
|
|
396
393
|
} else {
|
394
|
+
int status;
|
397
395
|
close(p[1]);
|
398
396
|
|
399
397
|
// We give the child process a time limit. If it doesn't succeed in
|
@@ -404,10 +402,91 @@ runInSubprocessWithTimeLimit(AbortHandlerState &state, Callback callback, void *
|
|
404
402
|
fd.events = POLLIN | POLLHUP | POLLERR;
|
405
403
|
if (poll(&fd, 1, timeLimit) <= 0) {
|
406
404
|
kill(child, SIGKILL);
|
407
|
-
safePrintErr("Could not
|
405
|
+
safePrintErr("Could not run child process: it did not exit in time\n");
|
408
406
|
}
|
409
407
|
close(p[0]);
|
410
|
-
waitpid(child,
|
408
|
+
if (waitpid(child, &status, 0) == child) {
|
409
|
+
return status;
|
410
|
+
} else {
|
411
|
+
return -1;
|
412
|
+
}
|
413
|
+
}
|
414
|
+
}
|
415
|
+
|
416
|
+
static void
|
417
|
+
dumpFileDescriptorInfoWithLsof(AbortHandlerState &state, void *userData) {
|
418
|
+
char *end;
|
419
|
+
|
420
|
+
end = state.messageBuf;
|
421
|
+
end = appendULL(end, state.pid);
|
422
|
+
*end = '\0';
|
423
|
+
|
424
|
+
closeAllFileDescriptors(2);
|
425
|
+
|
426
|
+
execlp("lsof", "lsof", "-p", state.messageBuf, "-nP", (const char * const) 0);
|
427
|
+
|
428
|
+
end = state.messageBuf;
|
429
|
+
end = appendText(end, "ERROR: cannot execute command 'lsof': errno=");
|
430
|
+
end = appendULL(end, errno);
|
431
|
+
end = appendText(end, "\n");
|
432
|
+
write(STDERR_FILENO, state.messageBuf, end - state.messageBuf);
|
433
|
+
_exit(1);
|
434
|
+
}
|
435
|
+
|
436
|
+
static void
|
437
|
+
dumpFileDescriptorInfoWithLs(AbortHandlerState &state, char *end) {
|
438
|
+
pid_t pid;
|
439
|
+
int status;
|
440
|
+
|
441
|
+
pid = asyncFork();
|
442
|
+
if (pid == 0) {
|
443
|
+
closeAllFileDescriptors(2);
|
444
|
+
// The '-v' is for natural sorting on Linux. On BSD -v means something else but it's harmless.
|
445
|
+
execlp("ls", "ls", "-lv", state.messageBuf, (const char * const) 0);
|
446
|
+
_exit(1);
|
447
|
+
} else if (pid == -1) {
|
448
|
+
safePrintErr("ERROR: Could not fork a process to dump file descriptor information!\n");
|
449
|
+
} else if (waitpid(pid, &status, 0) != pid || status != 0) {
|
450
|
+
safePrintErr("ERROR: Could not run 'ls' to dump file descriptor information!\n");
|
451
|
+
}
|
452
|
+
}
|
453
|
+
|
454
|
+
static void
|
455
|
+
dumpFileDescriptorInfo(AbortHandlerState &state) {
|
456
|
+
char *messageBuf = state.messageBuf;
|
457
|
+
char *end;
|
458
|
+
struct stat buf;
|
459
|
+
int status;
|
460
|
+
|
461
|
+
end = messageBuf;
|
462
|
+
end = appendText(end, state.messagePrefix);
|
463
|
+
end = appendText(end, " ] Open files and file descriptors:\n");
|
464
|
+
write(STDERR_FILENO, messageBuf, end - messageBuf);
|
465
|
+
|
466
|
+
status = runInSubprocessWithTimeLimit(state, dumpFileDescriptorInfoWithLsof, NULL, 4000);
|
467
|
+
|
468
|
+
if (status != 0) {
|
469
|
+
safePrintErr("Falling back to another mechanism for dumping file descriptors.\n");
|
470
|
+
|
471
|
+
end = messageBuf;
|
472
|
+
end = appendText(end, "/proc/");
|
473
|
+
end = appendULL(end, state.pid);
|
474
|
+
end = appendText(end, "/fd");
|
475
|
+
*end = '\0';
|
476
|
+
if (stat(messageBuf, &buf) == 0) {
|
477
|
+
dumpFileDescriptorInfoWithLs(state, end + 1);
|
478
|
+
} else {
|
479
|
+
end = messageBuf;
|
480
|
+
end = appendText(end, "/dev/fd");
|
481
|
+
*end = '\0';
|
482
|
+
if (stat(messageBuf, &buf) == 0) {
|
483
|
+
dumpFileDescriptorInfoWithLs(state, end + 1);
|
484
|
+
} else {
|
485
|
+
end = messageBuf;
|
486
|
+
end = appendText(end, "ERROR: No other file descriptor dumping mechanism on current platform detected.\n");
|
487
|
+
write(STDERR_FILENO, messageBuf, end - messageBuf);
|
488
|
+
}
|
489
|
+
}
|
411
490
|
}
|
412
491
|
}
|
413
492
|
|
@@ -421,6 +500,7 @@ dumpWithCrashWatch(AbortHandlerState &state) {
|
|
421
500
|
|
422
501
|
pid_t child = asyncFork();
|
423
502
|
if (child == 0) {
|
503
|
+
closeAllFileDescriptors(2);
|
424
504
|
execlp("crash-watch", "crash-watch", "--dump", pidStr, (char * const) 0);
|
425
505
|
if (errno == ENOENT) {
|
426
506
|
safePrintErr("Crash-watch is not installed. Please install it with 'gem install crash-watch' "
|
@@ -463,7 +543,7 @@ dumpWithCrashWatch(AbortHandlerState &state) {
|
|
463
543
|
end = appendText(end, " frames:\n");
|
464
544
|
write(STDERR_FILENO, state.messageBuf, end - state.messageBuf);
|
465
545
|
|
466
|
-
if (
|
546
|
+
if (backtraceSanitizerCommand != NULL) {
|
467
547
|
int p[2];
|
468
548
|
if (pipe(p) == -1) {
|
469
549
|
int e = errno;
|
@@ -482,34 +562,28 @@ dumpWithCrashWatch(AbortHandlerState &state) {
|
|
482
562
|
const char *pidStr = end = state.messageBuf;
|
483
563
|
end = appendULL(end, (unsigned long long) state.pid);
|
484
564
|
*end = '\0';
|
565
|
+
end++;
|
485
566
|
|
486
567
|
close(p[1]);
|
487
568
|
dup2(p[0], STDIN_FILENO);
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
execlp("/bin/sh", "/bin/sh", "-c",
|
499
|
-
state.messageBuf, (const char * const) 0);
|
500
|
-
} else {
|
501
|
-
if (backtraceSanitizerPassProgramInfo) {
|
502
|
-
execlp(backtraceSanitizerPath, backtraceSanitizerPath, argv0,
|
503
|
-
pidStr, (const char * const) 0);
|
504
|
-
} else {
|
505
|
-
execlp(backtraceSanitizerPath, backtraceSanitizerPath,
|
506
|
-
(const char * const) 0);
|
507
|
-
}
|
569
|
+
closeAllFileDescriptors(2);
|
570
|
+
|
571
|
+
char *command = end;
|
572
|
+
end = appendText(end, "exec ");
|
573
|
+
end = appendText(end, backtraceSanitizerCommand);
|
574
|
+
if (backtraceSanitizerPassProgramInfo) {
|
575
|
+
end = appendText(end, " \"");
|
576
|
+
end = appendText(end, argv0);
|
577
|
+
end = appendText(end, "\" ");
|
578
|
+
end = appendText(end, pidStr);
|
508
579
|
}
|
580
|
+
*end = '\0';
|
581
|
+
end++;
|
582
|
+
execlp("/bin/sh", "/bin/sh", "-c", command, (const char * const) 0);
|
509
583
|
|
510
584
|
end = state.messageBuf;
|
511
585
|
end = appendText(end, "ERROR: cannot execute '");
|
512
|
-
end = appendText(end,
|
586
|
+
end = appendText(end, backtraceSanitizerCommand);
|
513
587
|
end = appendText(end, "' for sanitizing the backtrace, trying 'cat'...\n");
|
514
588
|
write(STDERR_FILENO, state.messageBuf, end - state.messageBuf);
|
515
589
|
execlp("cat", "cat", (const char * const) 0);
|
@@ -539,7 +613,7 @@ dumpWithCrashWatch(AbortHandlerState &state) {
|
|
539
613
|
if (waitpid(pid, &status, 0) == -1 || status != 0) {
|
540
614
|
end = state.messageBuf;
|
541
615
|
end = appendText(end, "ERROR: cannot execute '");
|
542
|
-
end = appendText(end,
|
616
|
+
end = appendText(end, backtraceSanitizerCommand);
|
543
617
|
end = appendText(end, "' for sanitizing the backtrace, writing to stderr directly...\n");
|
544
618
|
write(STDERR_FILENO, state.messageBuf, end - state.messageBuf);
|
545
619
|
backtrace_symbols_fd(backtraceStore, frames, STDERR_FILENO);
|
@@ -563,27 +637,49 @@ dumpDiagnostics(AbortHandlerState &state) {
|
|
563
637
|
char *messageBuf = state.messageBuf;
|
564
638
|
char *end;
|
565
639
|
pid_t pid;
|
640
|
+
int status;
|
641
|
+
|
642
|
+
end = messageBuf;
|
643
|
+
end = appendText(end, state.messagePrefix);
|
644
|
+
end = appendText(end, " ] Date, uname and ulimits:\n");
|
645
|
+
write(STDERR_FILENO, messageBuf, end - messageBuf);
|
566
646
|
|
567
647
|
// Dump human-readable time string and string.
|
568
648
|
pid = asyncFork();
|
569
649
|
if (pid == 0) {
|
650
|
+
closeAllFileDescriptors(2);
|
570
651
|
execlp("date", "date", (const char * const) 0);
|
571
652
|
_exit(1);
|
572
653
|
} else if (pid == -1) {
|
573
654
|
safePrintErr("ERROR: Could not fork a process to dump the time!\n");
|
574
|
-
} else {
|
575
|
-
|
655
|
+
} else if (waitpid(pid, &status, 0) != pid || status != 0) {
|
656
|
+
safePrintErr("ERROR: Could not run 'date'!\n");
|
576
657
|
}
|
577
658
|
|
578
659
|
// Dump system uname.
|
579
660
|
pid = asyncFork();
|
580
661
|
if (pid == 0) {
|
662
|
+
closeAllFileDescriptors(2);
|
581
663
|
execlp("uname", "uname", "-mprsv", (const char * const) 0);
|
582
664
|
_exit(1);
|
583
665
|
} else if (pid == -1) {
|
584
666
|
safePrintErr("ERROR: Could not fork a process to dump the uname!\n");
|
585
|
-
} else {
|
586
|
-
|
667
|
+
} else if (waitpid(pid, &status, 0) != pid || status != 0) {
|
668
|
+
safePrintErr("ERROR: Could not run 'uname -mprsv'!\n");
|
669
|
+
}
|
670
|
+
|
671
|
+
// Dump ulimit.
|
672
|
+
pid = asyncFork();
|
673
|
+
if (pid == 0) {
|
674
|
+
closeAllFileDescriptors(2);
|
675
|
+
execlp("ulimit", "ulimit", "-a", (const char * const) 0);
|
676
|
+
// On Linux 'ulimit' is a shell builtin, not a command.
|
677
|
+
execlp("/bin/sh", "/bin/sh", "-c", "ulimit -a", (const char * const) 0);
|
678
|
+
_exit(1);
|
679
|
+
} else if (pid == -1) {
|
680
|
+
safePrintErr("ERROR: Could not fork a process to dump the ulimit!\n");
|
681
|
+
} else if (waitpid(pid, &status, 0) != pid || status != 0) {
|
682
|
+
safePrintErr("ERROR: Could not run 'ulimit -a'!\n");
|
587
683
|
}
|
588
684
|
|
589
685
|
end = messageBuf;
|
@@ -638,6 +734,9 @@ dumpDiagnostics(AbortHandlerState &state) {
|
|
638
734
|
safePrintErr("--------------------------------------\n");
|
639
735
|
}
|
640
736
|
|
737
|
+
dumpFileDescriptorInfo(state);
|
738
|
+
safePrintErr("--------------------------------------\n");
|
739
|
+
|
641
740
|
if (shouldDumpWithCrashWatch) {
|
642
741
|
end = messageBuf;
|
643
742
|
end = appendText(end, state.messagePrefix);
|
@@ -753,6 +852,13 @@ abortHandler(int signo, siginfo_t *info, void *ctx) {
|
|
753
852
|
return;
|
754
853
|
}
|
755
854
|
|
855
|
+
close(emergencyPipe1[0]);
|
856
|
+
close(emergencyPipe1[1]);
|
857
|
+
close(emergencyPipe2[0]);
|
858
|
+
close(emergencyPipe2[1]);
|
859
|
+
emergencyPipe1[0] = emergencyPipe1[1] = -1;
|
860
|
+
emergencyPipe2[0] = emergencyPipe2[1] = -1;
|
861
|
+
|
756
862
|
/* We want to dump the entire crash log to both stderr and a log file.
|
757
863
|
* We use 'tee' for this.
|
758
864
|
*/
|
@@ -798,6 +904,7 @@ abortHandler(int signo, siginfo_t *info, void *ctx) {
|
|
798
904
|
|
799
905
|
child = asyncFork();
|
800
906
|
if (child == 0) {
|
907
|
+
closeAllFileDescriptors(2);
|
801
908
|
#ifdef __APPLE__
|
802
909
|
execlp("osascript", "osascript", "-e", "beep 2", (const char * const) 0);
|
803
910
|
safePrintErr("Cannot execute 'osascript' command\n");
|
@@ -1338,6 +1445,8 @@ initializeAgent(int argc, char *argv[], const char *processName) {
|
|
1338
1445
|
shouldDumpWithCrashWatch = hasEnvOption("PASSENGER_DUMP_WITH_CRASH_WATCH", true);
|
1339
1446
|
beepOnAbort = hasEnvOption("PASSENGER_BEEP_ON_ABORT", false);
|
1340
1447
|
stopOnAbort = hasEnvOption("PASSENGER_STOP_ON_ABORT", false);
|
1448
|
+
pipe(emergencyPipe1);
|
1449
|
+
pipe(emergencyPipe2);
|
1341
1450
|
installAbortHandler();
|
1342
1451
|
}
|
1343
1452
|
oxt::initialize();
|
@@ -1380,12 +1489,14 @@ initializeAgent(int argc, char *argv[], const char *processName) {
|
|
1380
1489
|
#ifdef __linux__
|
1381
1490
|
if (options.has("passenger_root")) {
|
1382
1491
|
ResourceLocator locator(options.get("passenger_root", true));
|
1383
|
-
|
1492
|
+
string ruby = options.get("default_ruby", false, DEFAULT_RUBY);
|
1493
|
+
string path = ruby + " \"" + locator.getHelperScriptsDir() +
|
1494
|
+
"/backtrace-sanitizer.rb\"";
|
1495
|
+
backtraceSanitizerCommand = strdup(path.c_str());
|
1384
1496
|
}
|
1385
1497
|
#endif
|
1386
|
-
if (
|
1387
|
-
|
1388
|
-
backtraceSanitizerUseShell = true;
|
1498
|
+
if (backtraceSanitizerCommand == NULL) {
|
1499
|
+
backtraceSanitizerCommand = "c++filt -n";
|
1389
1500
|
backtraceSanitizerPassProgramInfo = false;
|
1390
1501
|
}
|
1391
1502
|
|