passenger 5.3.4 → 5.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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;
|