passenger 5.3.4 → 5.3.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +13 -0
- data/CODE_OF_CONDUCT.md +1 -1
- data/build/cxx_tests.rb +12 -1
- data/build/misc.rb +2 -1
- data/build/packaging.rb +2 -0
- data/build/support/cplusplus.rb +2 -2
- data/build/support/cxx_dependency_map.rb +653 -383
- data/dev/configkit-schemas/index.json +105 -3
- data/dev/show-latest-crashlog-dir +27 -0
- data/resources/templates/standalone/http.erb +2 -0
- data/src/agent/Core/AdminPanelConnector.h +2 -2
- data/src/agent/Core/ApplicationPool/Context.h +5 -1
- data/src/agent/Core/ApplicationPool/Group.h +2 -0
- data/src/agent/Core/ApplicationPool/Group/LifetimeAndBasics.cpp +5 -0
- data/src/agent/Core/ApplicationPool/Group/Miscellaneous.cpp +2 -1
- data/src/agent/Core/ApplicationPool/Group/ProcessListManagement.cpp +1 -1
- data/src/agent/Core/ApplicationPool/Group/StateInspection.cpp +12 -19
- data/src/agent/Core/ApplicationPool/Options.h +35 -31
- data/src/agent/Core/ApplicationPool/Pool/GroupUtils.cpp +2 -1
- data/src/agent/Core/ApplicationPool/Socket.h +1 -1
- data/src/agent/Core/Config.h +38 -7
- data/src/agent/Core/ConfigChange.cpp +13 -1
- data/src/agent/Core/Controller.h +3 -1
- data/src/agent/Core/Controller/Config.h +14 -11
- data/src/agent/Core/Controller/InitRequest.cpp +6 -5
- data/src/agent/Core/Controller/InitializationAndShutdown.cpp +3 -0
- data/src/agent/Core/CoreMain.cpp +149 -34
- data/src/agent/Core/OptionParser.h +12 -1
- data/src/agent/Core/SpawningKit/Config.h +1 -1
- data/src/agent/Core/SpawningKit/Context.h +7 -1
- data/src/agent/Core/SpawningKit/Exceptions.h +15 -12
- data/src/agent/Core/SpawningKit/README.md +34 -17
- data/src/agent/Core/SpawningKit/Spawner.h +5 -3
- data/src/agent/Core/SpawningKit/UserSwitchingRules.h +5 -2
- data/src/agent/Core/TelemetryCollector.h +674 -0
- data/src/agent/Shared/Fundamentals/AbortHandler.cpp +309 -83
- data/src/agent/Shared/Fundamentals/AbortHandler.h +18 -3
- data/src/agent/Watchdog/Config.h +21 -4
- data/src/agent/Watchdog/WatchdogMain.cpp +4 -1
- data/src/apache2_module/ConfigGeneral/AutoGeneratedDefinitions.cpp +10 -0
- data/src/apache2_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.cpp +5 -0
- data/src/apache2_module/ConfigGeneral/AutoGeneratedSetterFuncs.cpp +30 -0
- data/src/apache2_module/DirectoryMapper.h +24 -36
- data/src/apache2_module/Hooks.cpp +13 -5
- data/src/apache2_module/ServerConfig/AutoGeneratedManifestGeneration.cpp +20 -0
- data/src/apache2_module/ServerConfig/AutoGeneratedStruct.h +24 -0
- data/src/cxx_supportlib/AppTypeDetector/CBindings.cpp +136 -0
- data/src/cxx_supportlib/AppTypeDetector/CBindings.h +73 -0
- data/src/cxx_supportlib/{AppTypes.h → AppTypeDetector/Detector.h} +59 -132
- data/src/cxx_supportlib/ConfigKit/README.md +90 -2
- data/src/cxx_supportlib/ConfigKit/Schema.h +58 -13
- data/src/cxx_supportlib/ConfigKit/Store.h +128 -4
- data/src/cxx_supportlib/Constants.h +1 -1
- data/src/cxx_supportlib/ProcessManagement/Ruby.cpp +3 -3
- data/src/cxx_supportlib/ProcessManagement/Ruby.h +7 -2
- data/src/cxx_supportlib/ProcessManagement/Spawn.cpp +14 -7
- data/src/cxx_supportlib/ProcessManagement/Spawn.h +21 -2
- data/src/cxx_supportlib/ResourceLocator.h +1 -1
- data/src/cxx_supportlib/ServerKit/ClientRef.h +17 -7
- data/src/cxx_supportlib/ServerKit/HttpRequestRef.h +17 -7
- data/src/cxx_supportlib/Utils/IOUtils.cpp +2 -1
- data/src/cxx_supportlib/Utils/ProcessMetricsCollector.h +9 -6
- data/src/cxx_supportlib/WrapperRegistry/CBindings.cpp +85 -0
- data/src/cxx_supportlib/WrapperRegistry/CBindings.h +56 -0
- data/src/cxx_supportlib/WrapperRegistry/Entry.h +112 -0
- data/src/cxx_supportlib/WrapperRegistry/README.md +37 -0
- data/src/cxx_supportlib/WrapperRegistry/Registry.h +309 -0
- data/src/helper-scripts/download_binaries/extconf.rb +6 -2
- data/src/nginx_module/ConfigGeneral/AutoGeneratedDefinitions.c +16 -0
- data/src/nginx_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.c +6 -0
- data/src/nginx_module/ConfigGeneral/AutoGeneratedSetterFuncs.c +24 -0
- data/src/nginx_module/ContentHandler.c +34 -13
- data/src/nginx_module/ContentHandler.h +3 -3
- data/src/nginx_module/MainConfig/AutoGeneratedCreateFunction.c +11 -0
- data/src/nginx_module/MainConfig/AutoGeneratedManifestGeneration.c +23 -0
- data/src/nginx_module/MainConfig/AutoGeneratedStruct.h +8 -0
- data/src/nginx_module/config +2 -1
- data/src/nginx_module/ngx_http_passenger_module.c +9 -3
- data/src/nginx_module/ngx_http_passenger_module.h +4 -2
- data/src/ruby_supportlib/phusion_passenger.rb +2 -1
- data/src/ruby_supportlib/phusion_passenger/apache2/config_options.rb +13 -0
- data/src/ruby_supportlib/phusion_passenger/common_library.rb +8 -5
- data/src/ruby_supportlib/phusion_passenger/config/download_agent_command.rb +6 -2
- data/src/ruby_supportlib/phusion_passenger/config/download_nginx_engine_command.rb +6 -2
- data/src/ruby_supportlib/phusion_passenger/native_support.rb +7 -3
- data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +15 -0
- data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +11 -1
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +3 -1
- metadata +12 -4
- data/src/cxx_supportlib/AppTypes.cpp +0 -109
@@ -59,6 +59,7 @@
|
|
59
59
|
#include <LoggingKit/LoggingKit.h>
|
60
60
|
#include <LoggingKit/Context.h>
|
61
61
|
#include <ResourceLocator.h>
|
62
|
+
#include <RandomGenerator.h>
|
62
63
|
#include <ProcessManagement/Utils.h>
|
63
64
|
#include <Utils.h>
|
64
65
|
#include <Utils/AsyncSignalSafeUtils.h>
|
@@ -70,6 +71,9 @@ namespace Fundamentals {
|
|
70
71
|
using namespace std;
|
71
72
|
namespace ASSU = AsyncSignalSafeUtils;
|
72
73
|
|
74
|
+
#define RANDOM_TOKEN_SIZE 6
|
75
|
+
#define MAX_RANDOM_TOKENS 256
|
76
|
+
|
73
77
|
|
74
78
|
struct AbortHandlerContext {
|
75
79
|
const AbortHandlerConfig *config;
|
@@ -80,6 +84,12 @@ struct AbortHandlerContext {
|
|
80
84
|
char *backtraceSanitizerCommand;
|
81
85
|
bool backtraceSanitizerPassProgramInfo;
|
82
86
|
|
87
|
+
/**
|
88
|
+
* A string of RANDOM_TOKEN_SIZE * MAX_RANDOM_SIZES bytes.
|
89
|
+
* Used by createCrashLogDir() to find a unique directory name.
|
90
|
+
*/
|
91
|
+
char *randomTokens;
|
92
|
+
|
83
93
|
int emergencyPipe1[2];
|
84
94
|
int emergencyPipe2[2];
|
85
95
|
|
@@ -92,8 +102,12 @@ struct AbortHandlerWorkingState {
|
|
92
102
|
pid_t pid;
|
93
103
|
int signo;
|
94
104
|
siginfo_t *info;
|
105
|
+
|
95
106
|
char messagePrefix[32];
|
96
107
|
char messageBuf[1024];
|
108
|
+
|
109
|
+
char crashLogDir[256];
|
110
|
+
int crashLogDirFd;
|
97
111
|
};
|
98
112
|
|
99
113
|
typedef void (*Callback)(AbortHandlerWorkingState &state, void *userData);
|
@@ -116,6 +130,34 @@ write_nowarn(int fd, const void *buf, size_t n) {
|
|
116
130
|
ASSU::writeNoWarn(fd, buf, n);
|
117
131
|
}
|
118
132
|
|
133
|
+
static void
|
134
|
+
printCrashLogFileCreated(AbortHandlerWorkingState &state, const char *fname) {
|
135
|
+
const char *end = state.messageBuf + sizeof(state.messageBuf);
|
136
|
+
char *pos = state.messageBuf;
|
137
|
+
pos = ASSU::appendData(pos, end, "Dumping to ");
|
138
|
+
pos = ASSU::appendData(pos, end, state.crashLogDir);
|
139
|
+
pos = ASSU::appendData(pos, end, "/");
|
140
|
+
pos = ASSU::appendData(pos, end, fname);
|
141
|
+
pos = ASSU::appendData(pos, end, "\n");
|
142
|
+
write_nowarn(STDERR_FILENO, state.messageBuf, pos - state.messageBuf);
|
143
|
+
}
|
144
|
+
|
145
|
+
static void
|
146
|
+
printCrashLogFileCreationError(AbortHandlerWorkingState &state, const char *fname, int e) {
|
147
|
+
const char *end = state.messageBuf + sizeof(state.messageBuf);
|
148
|
+
char *pos = state.messageBuf;
|
149
|
+
pos = ASSU::appendData(pos, end, "Error creating ");
|
150
|
+
pos = ASSU::appendData(pos, end, state.crashLogDir);
|
151
|
+
pos = ASSU::appendData(pos, end, "/");
|
152
|
+
pos = ASSU::appendData(pos, end, fname);
|
153
|
+
pos = ASSU::appendData(pos, end, ": ");
|
154
|
+
pos = ASSU::appendData(pos, end, ASSU::limitedStrerror(e));
|
155
|
+
pos = ASSU::appendData(pos, end, " (errno=");
|
156
|
+
pos = ASSU::appendInteger<int, 10>(pos, end, e);
|
157
|
+
pos = ASSU::appendData(pos, end, ")\n");
|
158
|
+
write_nowarn(STDERR_FILENO, state.messageBuf, pos - state.messageBuf);
|
159
|
+
}
|
160
|
+
|
119
161
|
static char *
|
120
162
|
appendSignalName(char *pos, const char *end, int signo) {
|
121
163
|
switch (signo) {
|
@@ -289,8 +331,61 @@ runInSubprocessWithTimeLimit(AbortHandlerWorkingState &state, Callback callback,
|
|
289
331
|
}
|
290
332
|
}
|
291
333
|
|
334
|
+
static void
|
335
|
+
dumpUlimits(AbortHandlerWorkingState &state) {
|
336
|
+
const char *end = state.messageBuf + sizeof(state.messageBuf);
|
337
|
+
char *pos = state.messageBuf;
|
338
|
+
pos = ASSU::appendData(pos, end, state.messagePrefix);
|
339
|
+
pos = ASSU::appendData(pos, end, " ] Dumping ulimits...\n");
|
340
|
+
write_nowarn(STDERR_FILENO, state.messageBuf, pos - state.messageBuf);
|
341
|
+
|
342
|
+
int fd = -1;
|
343
|
+
if (state.crashLogDirFd != -1) {
|
344
|
+
fd = openat(state.crashLogDirFd, "ulimits.log", O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
345
|
+
if (fd != -1) {
|
346
|
+
printCrashLogFileCreated(state, "ulimits.log");
|
347
|
+
} else {
|
348
|
+
printCrashLogFileCreationError(state, "ulimits.log", errno);
|
349
|
+
}
|
350
|
+
}
|
351
|
+
|
352
|
+
pid_t pid = asyncFork();
|
353
|
+
int status;
|
354
|
+
if (pid == 0) {
|
355
|
+
if (fd != -1) {
|
356
|
+
dup2(fd, STDOUT_FILENO);
|
357
|
+
dup2(fd, STDERR_FILENO);
|
358
|
+
}
|
359
|
+
closeAllFileDescriptors(2, true);
|
360
|
+
execlp("ulimit", "ulimit", "-a", (const char * const) 0);
|
361
|
+
// On Linux 'ulimit' is a shell builtin, not a command.
|
362
|
+
execlp("/bin/sh", "/bin/sh", "-c", "ulimit -a", (const char * const) 0);
|
363
|
+
_exit(1);
|
364
|
+
} else if (pid == -1) {
|
365
|
+
ASSU::printError("ERROR: Could not fork a process to dump the ulimit!\n");
|
366
|
+
} else if (waitpid(pid, &status, 0) != pid || status != 0) {
|
367
|
+
ASSU::printError("ERROR: Could not run 'ulimit -a'!\n");
|
368
|
+
}
|
369
|
+
|
370
|
+
if (fd != -1) {
|
371
|
+
close(fd);
|
372
|
+
}
|
373
|
+
}
|
374
|
+
|
292
375
|
static void
|
293
376
|
dumpFileDescriptorInfoWithLsof(AbortHandlerWorkingState &state, void *userData) {
|
377
|
+
if (state.crashLogDirFd != -1) {
|
378
|
+
int fd = openat(state.crashLogDirFd, "fds.log", O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
379
|
+
if (fd != -1) {
|
380
|
+
printCrashLogFileCreated(state, "fds.log");
|
381
|
+
dup2(fd, STDOUT_FILENO);
|
382
|
+
dup2(fd, STDERR_FILENO);
|
383
|
+
close(fd);
|
384
|
+
} else {
|
385
|
+
printCrashLogFileCreationError(state, "fds.log", errno);
|
386
|
+
}
|
387
|
+
}
|
388
|
+
|
294
389
|
char *pos = state.messageBuf;
|
295
390
|
const char *end = state.messageBuf + sizeof(state.messageBuf) - 1;
|
296
391
|
pos = ASSU::appendInteger<pid_t, 10>(pos, end, state.pid);
|
@@ -306,15 +401,38 @@ dumpFileDescriptorInfoWithLsof(AbortHandlerWorkingState &state, void *userData)
|
|
306
401
|
}
|
307
402
|
|
308
403
|
static void
|
309
|
-
dumpFileDescriptorInfoWithLs(AbortHandlerWorkingState &state) {
|
404
|
+
dumpFileDescriptorInfoWithLs(AbortHandlerWorkingState &state, const char *path) {
|
310
405
|
pid_t pid;
|
406
|
+
int fd = -1;
|
311
407
|
int status;
|
312
408
|
|
409
|
+
if (state.crashLogDirFd != -1) {
|
410
|
+
fd = openat(state.crashLogDirFd, "fds.log", O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
411
|
+
if (fd != -1) {
|
412
|
+
printCrashLogFileCreated(state, "fds.log");
|
413
|
+
} else {
|
414
|
+
printCrashLogFileCreationError(state, "fds.log", errno);
|
415
|
+
}
|
416
|
+
}
|
417
|
+
|
313
418
|
pid = asyncFork();
|
314
419
|
if (pid == 0) {
|
420
|
+
if (fd != -1) {
|
421
|
+
dup2(fd, STDOUT_FILENO);
|
422
|
+
dup2(fd, STDERR_FILENO);
|
423
|
+
}
|
424
|
+
|
425
|
+
const char *end = state.messageBuf + sizeof(state.messageBuf);
|
426
|
+
char *pos = state.messageBuf;
|
427
|
+
pos = ASSU::appendData(pos, end, "Running: ls -lv ");
|
428
|
+
pos = ASSU::appendData(pos, end, path);
|
429
|
+
pos = ASSU::appendData(pos, end, "\n");
|
430
|
+
pos = ASSU::appendData(pos, end, "--------------------------\n");
|
431
|
+
write_nowarn(STDERR_FILENO, state.messageBuf, pos - state.messageBuf);
|
432
|
+
|
315
433
|
closeAllFileDescriptors(2, true);
|
316
434
|
// The '-v' is for natural sorting on Linux. On BSD -v means something else but it's harmless.
|
317
|
-
execlp("ls", "ls", "-lv",
|
435
|
+
execlp("ls", "ls", "-lv", path, (const char * const) 0);
|
318
436
|
|
319
437
|
const char *command[] = { "ls", NULL };
|
320
438
|
printExecError2(command, errno, state.messageBuf, sizeof(state.messageBuf));
|
@@ -324,6 +442,10 @@ dumpFileDescriptorInfoWithLs(AbortHandlerWorkingState &state) {
|
|
324
442
|
} else if (waitpid(pid, &status, 0) != pid || status != 0) {
|
325
443
|
ASSU::printError("ERROR: Could not run 'ls' to dump file descriptor information!\n");
|
326
444
|
}
|
445
|
+
|
446
|
+
if (fd != -1) {
|
447
|
+
close(fd);
|
448
|
+
}
|
327
449
|
}
|
328
450
|
|
329
451
|
static void
|
@@ -342,41 +464,58 @@ dumpFileDescriptorInfo(AbortHandlerWorkingState &state) {
|
|
342
464
|
status = runInSubprocessWithTimeLimit(state, dumpFileDescriptorInfoWithLsof, NULL, 4000);
|
343
465
|
|
344
466
|
if (status != 0) {
|
467
|
+
char path[256];
|
345
468
|
ASSU::printError("Falling back to another mechanism for dumping file descriptors.\n");
|
346
469
|
|
347
|
-
pos =
|
470
|
+
pos = path;
|
471
|
+
end = path + sizeof(path) - 1;
|
348
472
|
pos = ASSU::appendData(pos, end, "/proc/");
|
349
473
|
pos = ASSU::appendInteger<pid_t, 10>(pos, end, state.pid);
|
350
474
|
pos = ASSU::appendData(pos, end, "/fd");
|
351
475
|
*pos = '\0';
|
352
|
-
if (stat(
|
353
|
-
dumpFileDescriptorInfoWithLs(state);
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
write_nowarn(STDERR_FILENO, messageBuf, pos - messageBuf);
|
364
|
-
}
|
476
|
+
if (stat(path, &buf) == 0) {
|
477
|
+
dumpFileDescriptorInfoWithLs(state, path);
|
478
|
+
return;
|
479
|
+
}
|
480
|
+
|
481
|
+
pos = path;
|
482
|
+
pos = ASSU::appendData(pos, end, "/dev/fd");
|
483
|
+
*pos = '\0';
|
484
|
+
if (stat(path, &buf) == 0) {
|
485
|
+
dumpFileDescriptorInfoWithLs(state, path);
|
486
|
+
return;
|
365
487
|
}
|
488
|
+
|
489
|
+
pos = messageBuf;
|
490
|
+
pos = ASSU::appendData(pos, end, "ERROR: No other file descriptor dumping mechanism on current platform detected.\n");
|
491
|
+
write_nowarn(STDERR_FILENO, messageBuf, pos - messageBuf);
|
366
492
|
}
|
367
493
|
}
|
368
494
|
|
369
495
|
static void
|
370
496
|
dumpWithCrashWatch(AbortHandlerWorkingState &state) {
|
371
|
-
|
372
|
-
const char *end = state.messageBuf + sizeof(state.messageBuf) - 1;
|
497
|
+
int fd = -1;
|
373
498
|
|
374
|
-
|
499
|
+
if (state.crashLogDirFd != -1) {
|
500
|
+
fd = openat(state.crashLogDirFd, "backtrace.log", O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
501
|
+
if (fd != -1) {
|
502
|
+
printCrashLogFileCreated(state, "backtrace.log");
|
503
|
+
} else {
|
504
|
+
printCrashLogFileCreationError(state, "backtrace.log", errno);
|
505
|
+
}
|
506
|
+
}
|
507
|
+
|
508
|
+
char *pos = state.messageBuf;
|
509
|
+
const char *end = state.messageBuf + sizeof(state.messageBuf) - 1;
|
375
510
|
pos = ASSU::appendInteger<pid_t, 10>(pos, end, state.pid);
|
376
511
|
*pos = '\0';
|
377
512
|
|
378
513
|
pid_t child = asyncFork();
|
379
514
|
if (child == 0) {
|
515
|
+
if (fd != -1) {
|
516
|
+
dup2(fd, STDOUT_FILENO);
|
517
|
+
dup2(fd, STDERR_FILENO);
|
518
|
+
}
|
380
519
|
closeAllFileDescriptors(2, true);
|
381
520
|
execlp(ctx->config->ruby, ctx->config->ruby, ctx->crashWatchCommand,
|
382
521
|
ctx->rubyLibDir, ctx->installSpec, "--dump",
|
@@ -400,6 +539,10 @@ dumpWithCrashWatch(AbortHandlerWorkingState &state) {
|
|
400
539
|
} else {
|
401
540
|
waitpid(child, NULL, 0);
|
402
541
|
}
|
542
|
+
|
543
|
+
if (fd != -1) {
|
544
|
+
close(fd);
|
545
|
+
}
|
403
546
|
}
|
404
547
|
|
405
548
|
#ifdef LIBC_HAS_BACKTRACE_FUNC
|
@@ -508,7 +651,22 @@ dumpWithCrashWatch(AbortHandlerWorkingState &state) {
|
|
508
651
|
|
509
652
|
static void
|
510
653
|
runCustomDiagnosticsDumper(AbortHandlerWorkingState &state, void *userData) {
|
511
|
-
|
654
|
+
unsigned int i = static_cast<unsigned int>(reinterpret_cast<boost::uintptr_t>(userData));
|
655
|
+
const AbortHandlerConfig::DiagnosticsDumper &dumper = ctx->config->diagnosticsDumpers[i];
|
656
|
+
|
657
|
+
if (state.crashLogDirFd != -1) {
|
658
|
+
int fd = openat(state.crashLogDirFd, dumper.logFileName, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
659
|
+
if (fd != -1) {
|
660
|
+
printCrashLogFileCreated(state, dumper.logFileName);
|
661
|
+
dup2(fd, STDOUT_FILENO);
|
662
|
+
dup2(fd, STDERR_FILENO);
|
663
|
+
close(fd);
|
664
|
+
} else {
|
665
|
+
printCrashLogFileCreationError(state, dumper.logFileName, errno);
|
666
|
+
}
|
667
|
+
}
|
668
|
+
|
669
|
+
dumper.func(dumper.userData);
|
512
670
|
}
|
513
671
|
|
514
672
|
// This function is performed in a child process.
|
@@ -521,7 +679,7 @@ dumpDiagnostics(AbortHandlerWorkingState &state) {
|
|
521
679
|
|
522
680
|
pos = state.messageBuf;
|
523
681
|
pos = ASSU::appendData(pos, end, state.messagePrefix);
|
524
|
-
pos = ASSU::appendData(pos, end, " ] Date
|
682
|
+
pos = ASSU::appendData(pos, end, " ] Date and uname:\n");
|
525
683
|
write_nowarn(STDERR_FILENO, state.messageBuf, pos - state.messageBuf);
|
526
684
|
|
527
685
|
// Dump human-readable time string and string.
|
@@ -548,20 +706,6 @@ dumpDiagnostics(AbortHandlerWorkingState &state) {
|
|
548
706
|
ASSU::printError("ERROR: Could not run 'uname -mprsv'!\n");
|
549
707
|
}
|
550
708
|
|
551
|
-
// Dump ulimit.
|
552
|
-
pid = asyncFork();
|
553
|
-
if (pid == 0) {
|
554
|
-
closeAllFileDescriptors(2, true);
|
555
|
-
execlp("ulimit", "ulimit", "-a", (const char * const) 0);
|
556
|
-
// On Linux 'ulimit' is a shell builtin, not a command.
|
557
|
-
execlp("/bin/sh", "/bin/sh", "-c", "ulimit -a", (const char * const) 0);
|
558
|
-
_exit(1);
|
559
|
-
} else if (pid == -1) {
|
560
|
-
ASSU::printError("ERROR: Could not fork a process to dump the ulimit!\n");
|
561
|
-
} else if (waitpid(pid, &status, 0) != pid || status != 0) {
|
562
|
-
ASSU::printError("ERROR: Could not run 'ulimit -a'!\n");
|
563
|
-
}
|
564
|
-
|
565
709
|
pos = state.messageBuf;
|
566
710
|
pos = ASSU::appendData(pos, end, state.messagePrefix);
|
567
711
|
pos = ASSU::appendData(pos, end, " ] " PROGRAM_NAME " version: " PASSENGER_VERSION "\n");
|
@@ -604,13 +748,24 @@ dumpDiagnostics(AbortHandlerWorkingState &state) {
|
|
604
748
|
|
605
749
|
ASSU::printError("--------------------------------------\n");
|
606
750
|
|
607
|
-
|
751
|
+
dumpUlimits(state);
|
752
|
+
|
753
|
+
ASSU::printError("--------------------------------------\n");
|
754
|
+
|
755
|
+
for (unsigned int i = 0; i < AbortHandlerConfig::MAX_DIAGNOSTICS_DUMPERS; i++) {
|
756
|
+
const AbortHandlerConfig::DiagnosticsDumper &diagnosticsDumper = ctx->config->diagnosticsDumpers[i];
|
757
|
+
if (diagnosticsDumper.func == NULL) {
|
758
|
+
continue;
|
759
|
+
}
|
760
|
+
|
608
761
|
pos = state.messageBuf;
|
609
762
|
pos = ASSU::appendData(pos, end, state.messagePrefix);
|
610
|
-
pos = ASSU::appendData(pos, end, " ] Dumping
|
763
|
+
pos = ASSU::appendData(pos, end, " ] Dumping ");
|
764
|
+
pos = ASSU::appendData(pos, end, diagnosticsDumper.name);
|
765
|
+
pos = ASSU::appendData(pos, end, "...\n");
|
611
766
|
write_nowarn(STDERR_FILENO, state.messageBuf, pos - state.messageBuf);
|
612
|
-
|
613
|
-
|
767
|
+
runInSubprocessWithTimeLimit(state, runCustomDiagnosticsDumper,
|
768
|
+
reinterpret_cast<void *>(static_cast<boost::uintptr_t>(i)), 2000);
|
614
769
|
ASSU::printError("--------------------------------------\n");
|
615
770
|
}
|
616
771
|
|
@@ -630,46 +785,109 @@ dumpDiagnostics(AbortHandlerWorkingState &state) {
|
|
630
785
|
} else {
|
631
786
|
write_nowarn(STDERR_FILENO, "\n", 1);
|
632
787
|
}
|
788
|
+
|
789
|
+
if (state.crashLogDir[0] != '\0') {
|
790
|
+
ASSU::printError("--------------------------------------\n");
|
791
|
+
pos = state.messageBuf;
|
792
|
+
pos = ASSU::appendData(pos, end, state.messagePrefix);
|
793
|
+
pos = ASSU::appendData(pos, end, " ] **************** LOOK HERE FOR CRASH DETAILS *****************\n\n");
|
794
|
+
pos = ASSU::appendData(pos, end, state.messagePrefix);
|
795
|
+
pos = ASSU::appendData(pos, end, " ] Crash log dumped to this directory:\n");
|
796
|
+
pos = ASSU::appendData(pos, end, state.messagePrefix);
|
797
|
+
pos = ASSU::appendData(pos, end, " ] ");
|
798
|
+
pos = ASSU::appendData(pos, end, state.crashLogDir);
|
799
|
+
pos = ASSU::appendData(pos, end, "\n\n");
|
800
|
+
pos = ASSU::appendData(pos, end, state.messagePrefix);
|
801
|
+
pos = ASSU::appendData(pos, end, " ] **************** LOOK ABOVE FOR CRASH DETAILS ****************\n");
|
802
|
+
write_nowarn(STDERR_FILENO, state.messageBuf, pos - state.messageBuf);
|
803
|
+
}
|
633
804
|
}
|
634
805
|
|
635
806
|
static bool
|
636
|
-
|
637
|
-
char *
|
638
|
-
const char *end =
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
pos =
|
646
|
-
pos = ASSU::appendData(pos, end, ctx->
|
647
|
-
|
648
|
-
pos = ASSU::appendInteger<time_t, 10>(pos, end, t);
|
807
|
+
createCrashLogDir(AbortHandlerWorkingState &state, time_t t) {
|
808
|
+
char *suffixBegin = state.crashLogDir;
|
809
|
+
const char *end = state.crashLogDir + sizeof(state.crashLogDir) - 1;
|
810
|
+
suffixBegin = ASSU::appendData(suffixBegin, end, "/var/tmp/passenger-crash-log.");
|
811
|
+
suffixBegin = ASSU::appendInteger<time_t, 10>(suffixBegin, end, t);
|
812
|
+
suffixBegin = ASSU::appendData(suffixBegin, end, ".");
|
813
|
+
|
814
|
+
// Try a bunch of times to find and create a unique path.
|
815
|
+
for (unsigned int i = 0; i < MAX_RANDOM_TOKENS; i++) {
|
816
|
+
char *pos = suffixBegin;
|
817
|
+
pos = ASSU::appendData(pos, end, ctx->randomTokens + RANDOM_TOKEN_SIZE * i,
|
818
|
+
RANDOM_TOKEN_SIZE);
|
649
819
|
*pos = '\0';
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
820
|
+
|
821
|
+
int ret;
|
822
|
+
do {
|
823
|
+
ret = mkdir(state.crashLogDir, 0700);
|
824
|
+
} while (ret == -1 && errno == EINTR);
|
825
|
+
if (ret == -1) {
|
826
|
+
if (errno == EEXIST) {
|
827
|
+
// Directory exists; try again.
|
828
|
+
continue;
|
829
|
+
} else {
|
830
|
+
int e = errno;
|
831
|
+
end = state.messageBuf + sizeof(state.messageBuf);
|
832
|
+
pos = state.messageBuf;
|
833
|
+
pos = ASSU::appendData(pos, end, state.messagePrefix);
|
834
|
+
pos = ASSU::appendData(pos, end, " ] Error creating directory ");
|
835
|
+
pos = ASSU::appendData(pos, end, state.crashLogDir);
|
836
|
+
pos = ASSU::appendData(pos, end, " for storing crash log: ");
|
837
|
+
pos = ASSU::appendData(pos, end, ASSU::limitedStrerror(e));
|
838
|
+
pos = ASSU::appendData(pos, end, " (errno=");
|
839
|
+
pos = ASSU::appendInteger<int, 10>(pos, end, e);
|
840
|
+
pos = ASSU::appendData(pos, end, ")\n");
|
841
|
+
write_nowarn(STDERR_FILENO, state.messageBuf, pos - state.messageBuf);
|
842
|
+
state.crashLogDir[0] = '\0';
|
843
|
+
return false;
|
844
|
+
}
|
845
|
+
}
|
846
|
+
|
847
|
+
do {
|
848
|
+
state.crashLogDirFd = open(state.crashLogDir, O_RDONLY);
|
849
|
+
} while (state.crashLogDirFd == -1 && errno == EINTR);
|
850
|
+
if (state.crashLogDirFd == -1) {
|
851
|
+
int e = errno;
|
852
|
+
end = state.messageBuf + sizeof(state.messageBuf);
|
853
|
+
pos = state.messageBuf;
|
854
|
+
pos = ASSU::appendData(pos, end, state.messagePrefix);
|
855
|
+
pos = ASSU::appendData(pos, end, " ] Error opening created directory ");
|
856
|
+
pos = ASSU::appendData(pos, end, state.crashLogDir);
|
857
|
+
pos = ASSU::appendData(pos, end, " for storing crash log: ");
|
858
|
+
pos = ASSU::appendData(pos, end, ASSU::limitedStrerror(e));
|
859
|
+
pos = ASSU::appendData(pos, end, " (errno=");
|
860
|
+
pos = ASSU::appendInteger<int, 10>(pos, end, e);
|
861
|
+
pos = ASSU::appendData(pos, end, ")\n");
|
862
|
+
write_nowarn(STDERR_FILENO, state.messageBuf, pos - state.messageBuf);
|
863
|
+
state.crashLogDir[0] = '\0';
|
864
|
+
return false;
|
865
|
+
}
|
866
|
+
|
657
867
|
return true;
|
658
868
|
}
|
869
|
+
|
870
|
+
state.crashLogDir[0] = '\0';
|
871
|
+
return false;
|
659
872
|
}
|
660
873
|
|
661
|
-
static
|
662
|
-
|
663
|
-
pid_t pid;
|
874
|
+
static bool
|
875
|
+
forkAndRedirectToTeeAndMainLogFile(const char *crashLogDir) {
|
664
876
|
int p[2];
|
665
|
-
|
666
877
|
if (pipe(p) == -1) {
|
667
|
-
|
668
|
-
*filename = '\0';
|
669
|
-
return;
|
878
|
+
return false;
|
670
879
|
}
|
671
880
|
|
672
|
-
|
881
|
+
char filename[300];
|
882
|
+
char *pos = filename;
|
883
|
+
const char *end = filename + sizeof(filename) - 1;
|
884
|
+
|
885
|
+
pos = ASSU::appendData(pos, end, crashLogDir);
|
886
|
+
pos = ASSU::appendData(pos, end, "/");
|
887
|
+
pos = ASSU::appendData(pos, end, "main.log");
|
888
|
+
*pos = '\0';
|
889
|
+
|
890
|
+
pid_t pid = asyncFork();
|
673
891
|
if (pid == 0) {
|
674
892
|
close(p[1]);
|
675
893
|
dup2(p[0], STDIN_FILENO);
|
@@ -680,13 +898,15 @@ forkAndRedirectToTee(char *filename) {
|
|
680
898
|
execlp("/usr/bin/cat", "cat", (const char * const) 0);
|
681
899
|
ASSU::printError("ERROR: cannot execute 'tee' or 'cat'; crash log will be lost!\n");
|
682
900
|
_exit(1);
|
901
|
+
return false;
|
683
902
|
} else if (pid == -1) {
|
684
903
|
ASSU::printError("ERROR: cannot fork a process for executing 'tee'\n");
|
685
|
-
|
904
|
+
return false;
|
686
905
|
} else {
|
687
906
|
close(p[0]);
|
688
907
|
dup2(p[1], STDOUT_FILENO);
|
689
908
|
dup2(p[1], STDERR_FILENO);
|
909
|
+
return true;
|
690
910
|
}
|
691
911
|
}
|
692
912
|
|
@@ -717,7 +937,6 @@ abortHandler(int signo, siginfo_t *info, void *_unused) {
|
|
717
937
|
state.info = info;
|
718
938
|
pid_t child;
|
719
939
|
time_t t = time(NULL);
|
720
|
-
char crashLogFile[256];
|
721
940
|
|
722
941
|
ctx->callCount++;
|
723
942
|
if (ctx->callCount > 1) {
|
@@ -756,13 +975,6 @@ abortHandler(int signo, siginfo_t *info, void *_unused) {
|
|
756
975
|
|
757
976
|
closeEmergencyPipes();
|
758
977
|
|
759
|
-
/* We want to dump the entire crash log to both stderr and a log file.
|
760
|
-
* We use 'tee' for this.
|
761
|
-
*/
|
762
|
-
if (createCrashLogFile(crashLogFile, sizeof(crashLogFile), t)) {
|
763
|
-
forkAndRedirectToTee(crashLogFile);
|
764
|
-
}
|
765
|
-
|
766
978
|
{
|
767
979
|
const char *end = state.messagePrefix + sizeof(state.messagePrefix);
|
768
980
|
char *pos = state.messagePrefix;
|
@@ -771,8 +983,19 @@ abortHandler(int signo, siginfo_t *info, void *_unused) {
|
|
771
983
|
*pos = '\0';
|
772
984
|
}
|
773
985
|
|
986
|
+
/* We want to dump the entire crash log to both stderr and a log file.
|
987
|
+
* We use 'tee' for this.
|
988
|
+
*/
|
989
|
+
state.crashLogDir[0] = '\0';
|
990
|
+
state.crashLogDirFd = -1;
|
991
|
+
if (createCrashLogDir(state, t)) {
|
992
|
+
forkAndRedirectToTeeAndMainLogFile(state.crashLogDir);
|
993
|
+
}
|
994
|
+
|
774
995
|
const char *end = state.messageBuf + sizeof(state.messageBuf);
|
775
996
|
char *pos = state.messageBuf;
|
997
|
+
// Print a \n just in case we're aborting in the middle of a non-terminated line.
|
998
|
+
pos = ASSU::appendData(pos, end, "\n");
|
776
999
|
pos = ASSU::appendData(pos, end, state.messagePrefix);
|
777
1000
|
pos = ASSU::appendData(pos, end, ", timestamp=");
|
778
1001
|
pos = ASSU::appendInteger<time_t, 10>(pos, end, t);
|
@@ -786,14 +1009,14 @@ abortHandler(int signo, siginfo_t *info, void *_unused) {
|
|
786
1009
|
write_nowarn(STDERR_FILENO, state.messageBuf, pos - state.messageBuf);
|
787
1010
|
|
788
1011
|
pos = state.messageBuf;
|
789
|
-
if (
|
1012
|
+
if (state.crashLogDir[0] != '\0') {
|
790
1013
|
pos = ASSU::appendData(pos, end, state.messagePrefix);
|
791
|
-
pos = ASSU::appendData(pos, end, " ] Crash log dumped to ");
|
792
|
-
pos = ASSU::appendData(pos, end,
|
793
|
-
pos = ASSU::appendData(pos, end, "
|
1014
|
+
pos = ASSU::appendData(pos, end, " ] Crash log files will be dumped to ");
|
1015
|
+
pos = ASSU::appendData(pos, end, state.crashLogDir);
|
1016
|
+
pos = ASSU::appendData(pos, end, " <--- ******* LOOK HERE FOR DETAILS!!! *******\n");
|
794
1017
|
} else {
|
795
1018
|
pos = ASSU::appendData(pos, end, state.messagePrefix);
|
796
|
-
pos = ASSU::appendData(pos, end, " ] Could not create crash log
|
1019
|
+
pos = ASSU::appendData(pos, end, " ] Could not create crash log directory, so dumping to stderr only.\n");
|
797
1020
|
}
|
798
1021
|
write_nowarn(STDERR_FILENO, state.messageBuf, pos - state.messageBuf);
|
799
1022
|
|
@@ -869,7 +1092,7 @@ abortHandler(int signo, siginfo_t *info, void *_unused) {
|
|
869
1092
|
int e = errno;
|
870
1093
|
pos = state.messageBuf;
|
871
1094
|
pos = ASSU::appendData(pos, end, state.messagePrefix);
|
872
|
-
pos = ASSU::appendData(pos, end, "] Could fork a child process for dumping diagnostics: fork() failed with errno=");
|
1095
|
+
pos = ASSU::appendData(pos, end, "] Could not fork a child process for dumping diagnostics: fork() failed with errno=");
|
873
1096
|
pos = ASSU::appendInteger<int, 10>(pos, end, e);
|
874
1097
|
pos = ASSU::appendData(pos, end, "\n");
|
875
1098
|
write_nowarn(STDERR_FILENO, state.messageBuf, pos - state.messageBuf);
|
@@ -884,7 +1107,7 @@ abortHandler(int signo, siginfo_t *info, void *_unused) {
|
|
884
1107
|
int e = errno;
|
885
1108
|
pos = state.messageBuf;
|
886
1109
|
pos = ASSU::appendData(pos, end, state.messagePrefix);
|
887
|
-
pos = ASSU::appendData(pos, end, " ] Could fork a child process for dumping diagnostics: fork() failed with errno=");
|
1110
|
+
pos = ASSU::appendData(pos, end, " ] Could not fork a child process for dumping diagnostics: fork() failed with errno=");
|
888
1111
|
pos = ASSU::appendInteger<int, 10>(pos, end, e);
|
889
1112
|
pos = ASSU::appendData(pos, end, "\n");
|
890
1113
|
write_nowarn(STDERR_FILENO, state.messageBuf, pos - state.messageBuf);
|
@@ -905,6 +1128,8 @@ installAbortHandler(const AbortHandlerConfig *config) {
|
|
905
1128
|
|
906
1129
|
ctx->config = config;
|
907
1130
|
ctx->backtraceSanitizerPassProgramInfo = true;
|
1131
|
+
ctx->randomTokens = strdup(RandomGenerator().generateAsciiString(
|
1132
|
+
MAX_RANDOM_TOKENS * RANDOM_TOKEN_SIZE).c_str());
|
908
1133
|
ctx->emergencyPipe1[0] = -1;
|
909
1134
|
ctx->emergencyPipe1[1] = -1;
|
910
1135
|
ctx->emergencyPipe2[0] = -1;
|
@@ -1038,6 +1263,7 @@ shutdownAbortHandler() {
|
|
1038
1263
|
free(ctx->tmpDir);
|
1039
1264
|
free(ctx->crashWatchCommand);
|
1040
1265
|
free(ctx->backtraceSanitizerCommand);
|
1266
|
+
free(ctx->randomTokens);
|
1041
1267
|
free(ctx->alternativeStack);
|
1042
1268
|
closeEmergencyPipes();
|
1043
1269
|
delete ctx;
|