passenger 5.1.7 → 5.1.8
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG +13 -2
- data/CONTRIBUTING.md +1 -1
- data/build/agent.rb +1 -1
- data/build/cxx_tests.rb +6 -0
- data/build/support/cxx_dependency_map.rb +1286 -391
- data/build/support/general.rb +0 -26
- data/resources/templates/standalone/rails_asset_pipeline.erb +2 -2
- data/src/agent/Core/ApiServer.h +49 -44
- data/src/agent/Core/ApplicationPool/Pool.h +1 -1
- data/src/agent/Core/ApplicationPool/Process.h +1 -1
- data/src/agent/Core/ApplicationPool/Socket.h +1 -1
- data/src/agent/Core/Controller.h +16 -8
- data/src/agent/Core/Controller/CheckoutSession.cpp +1 -1
- data/src/agent/Core/Controller/Config.cpp +68 -0
- data/src/agent/Core/Controller/Config.h +70 -34
- data/src/agent/Core/Controller/ForwardResponse.cpp +5 -5
- data/src/agent/Core/Controller/Hooks.cpp +5 -14
- data/src/agent/Core/Controller/Implementation.cpp +1 -1
- data/src/agent/Core/Controller/InitRequest.cpp +31 -29
- data/src/agent/Core/Controller/InitializationAndShutdown.cpp +4 -4
- data/src/agent/Core/Controller/InternalUtils.cpp +3 -3
- data/src/agent/Core/Controller/Miscellaneous.cpp +1 -1
- data/src/agent/Core/Controller/Request.h +2 -2
- data/src/agent/Core/Controller/SendRequest.cpp +5 -5
- data/src/agent/Core/Controller/StateInspection.cpp +1 -1
- data/src/agent/Core/Controller/TurboCaching.h +2 -2
- data/src/agent/Core/CoreMain.cpp +2 -2
- data/src/agent/Core/ResponseCache.h +3 -3
- data/src/agent/Core/SpawningKit/BackgroundIOCapturer.h +3 -3
- data/src/agent/Core/SpawningKit/DirectSpawner.h +2 -2
- data/src/agent/Core/SpawningKit/PipeWatcher.h +3 -3
- data/src/agent/Core/SpawningKit/SmartSpawner.h +2 -2
- data/src/agent/Core/SpawningKit/Spawner.h +1 -1
- data/src/agent/Core/UnionStation/Connection.h +1 -1
- data/src/agent/Core/UnionStation/Context.h +1 -1
- data/src/agent/Core/UnionStation/Transaction.h +1 -1
- data/src/agent/Shared/ApiServerUtils.h +73 -27
- data/src/agent/Shared/Base.cpp +61 -73
- data/src/agent/UstRouter/ApiServer.h +34 -45
- data/src/agent/UstRouter/Controller.h +86 -60
- data/src/agent/UstRouter/RemoteSender.h +1 -1
- data/src/agent/UstRouter/RemoteSink.h +1 -1
- data/src/agent/Watchdog/ApiServer.h +42 -50
- data/src/agent/Watchdog/WatchdogMain.cpp +1 -1
- data/src/apache2_module/Configuration.hpp +1 -1
- data/src/apache2_module/Hooks.cpp +27 -13
- data/src/cxx_supportlib/AppTypes.h +1 -1
- data/src/cxx_supportlib/BackgroundEventLoop.cpp +1 -1
- data/src/cxx_supportlib/ConfigKit/AsyncUtils.h +86 -0
- data/src/cxx_supportlib/ConfigKit/Common.h +6 -3
- data/src/cxx_supportlib/ConfigKit/IN_PRACTICE.md +1039 -0
- data/src/cxx_supportlib/ConfigKit/README.md +112 -497
- data/src/cxx_supportlib/ConfigKit/Schema.h +78 -15
- data/src/cxx_supportlib/ConfigKit/Store.h +272 -53
- data/src/cxx_supportlib/ConfigKit/SubComponentUtils.h +59 -0
- data/src/cxx_supportlib/ConfigKit/Utils.h +26 -65
- data/src/cxx_supportlib/ConfigKit/ValidationUtils.h +69 -0
- data/src/cxx_supportlib/ConfigKit/VariantMapUtils.h +7 -4
- data/src/cxx_supportlib/Constants.h +4 -1
- data/src/cxx_supportlib/Crypto.cpp +1 -1
- data/src/cxx_supportlib/DataStructures/StringKeyTable.h +26 -7
- data/src/cxx_supportlib/FileDescriptor.h +1 -1
- data/src/cxx_supportlib/Hooks.h +1 -1
- data/src/cxx_supportlib/LoggingKit/Assert.h +130 -0
- data/src/cxx_supportlib/LoggingKit/Config.h +97 -0
- data/src/cxx_supportlib/LoggingKit/Context.h +94 -0
- data/src/cxx_supportlib/LoggingKit/Forward.h +95 -0
- data/src/cxx_supportlib/LoggingKit/Implementation.cpp +695 -0
- data/src/cxx_supportlib/LoggingKit/Logging.h +204 -0
- data/src/cxx_supportlib/LoggingKit/LoggingKit.h +33 -0
- data/src/cxx_supportlib/LveLoggingDecorator.h +1 -1
- data/src/cxx_supportlib/MemoryKit/mbuf.cpp +1 -1
- data/src/cxx_supportlib/RandomGenerator.h +1 -1
- data/src/cxx_supportlib/SafeLibev.h +1 -1
- data/src/cxx_supportlib/ServerKit/AcceptLoadBalancer.h +1 -1
- data/src/cxx_supportlib/ServerKit/Channel.h +1 -1
- data/src/cxx_supportlib/ServerKit/FileBufferedChannel.h +1 -1
- data/src/cxx_supportlib/ServerKit/FileBufferedFdSinkChannel.h +1 -1
- data/src/cxx_supportlib/ServerKit/HttpChunkedBodyParser.h +1 -1
- data/src/cxx_supportlib/ServerKit/HttpHeaderParser.h +1 -1
- data/src/cxx_supportlib/ServerKit/HttpServer.h +48 -15
- data/src/cxx_supportlib/ServerKit/Server.h +79 -52
- data/src/cxx_supportlib/StaticString.h +12 -0
- data/src/cxx_supportlib/Utils/Curl.h +16 -0
- data/src/cxx_supportlib/Utils/FastStringStream.h +6 -1
- data/src/cxx_supportlib/Utils/ScopeGuard.h +1 -1
- data/src/cxx_supportlib/Utils/StrIntUtils.cpp +2 -19
- data/src/cxx_supportlib/WatchdogLauncher.h +3 -2
- data/src/ruby_supportlib/phusion_passenger.rb +3 -3
- data/src/ruby_supportlib/phusion_passenger/common_library.rb +12 -12
- data/src/ruby_supportlib/phusion_passenger/constants.rb +6 -3
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command.rb +1 -0
- data/src/ruby_supportlib/phusion_passenger/standalone/stop_command.rb +1 -0
- metadata +14 -4
- data/src/cxx_supportlib/Logging.cpp +0 -295
- data/src/cxx_supportlib/Logging.h +0 -385
@@ -43,6 +43,9 @@ module PhusionPassenger
|
|
43
43
|
module SharedConstants
|
44
44
|
# Default config values
|
45
45
|
DEFAULT_LOG_LEVEL = 3
|
46
|
+
DEFAULT_LOG_LEVEL_NAME = "notice"
|
47
|
+
DEFAULT_APP_OUTPUT_LOG_LEVEL = 3
|
48
|
+
DEFAULT_APP_OUTPUT_LOG_LEVEL_NAME = "notice"
|
46
49
|
DEFAULT_INTEGRATION_MODE = "standalone"
|
47
50
|
DEFAULT_SOCKET_BACKLOG = 2048
|
48
51
|
DEFAULT_RUBY = "ruby"
|
@@ -77,13 +80,13 @@ module PhusionPassenger
|
|
77
80
|
MESSAGE_SERVER_MAX_PASSWORD_SIZE = 100
|
78
81
|
POOL_HELPER_THREAD_STACK_SIZE = 1024 * 256
|
79
82
|
# Small mbuf sizes avoid memory overhead (up to 1 blocksize per request), but
|
80
|
-
# also introduce context switching and smaller transfer writes. The size is picked
|
83
|
+
# also introduce context switching and smaller transfer writes. The size is picked
|
81
84
|
# to balance this out.
|
82
85
|
DEFAULT_MBUF_CHUNK_SIZE = 1024 * 4
|
83
86
|
# Affects input and output buffering (between app and client). Threshold is picked
|
84
87
|
# such that it fits most output (i.e. html page size, not assets), and allows for
|
85
|
-
# high concurrency with low mem overhead. On the upload side there is a penalty
|
86
|
-
# but there's no real average upload size anyway so we choose mem safety instead.
|
88
|
+
# high concurrency with low mem overhead. On the upload side there is a penalty
|
89
|
+
# but there's no real average upload size anyway so we choose mem safety instead.
|
87
90
|
DEFAULT_FILE_BUFFERED_CHANNEL_THRESHOLD = 1024 * 128
|
88
91
|
SERVER_KIT_MAX_SERVER_ENDPOINTS = 4
|
89
92
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: passenger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.1.
|
4
|
+
version: 5.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Phusion - http://www.phusion.nl/
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-08-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -340,6 +340,7 @@ files:
|
|
340
340
|
- src/agent/Core/Controller/BufferBody.cpp
|
341
341
|
- src/agent/Core/Controller/CheckoutSession.cpp
|
342
342
|
- src/agent/Core/Controller/Client.h
|
343
|
+
- src/agent/Core/Controller/Config.cpp
|
343
344
|
- src/agent/Core/Controller/Config.h
|
344
345
|
- src/agent/Core/Controller/ForwardResponse.cpp
|
345
346
|
- src/agent/Core/Controller/Hooks.cpp
|
@@ -422,15 +423,19 @@ files:
|
|
422
423
|
- src/cxx_supportlib/AppTypes.h
|
423
424
|
- src/cxx_supportlib/BackgroundEventLoop.cpp
|
424
425
|
- src/cxx_supportlib/BackgroundEventLoop.h
|
426
|
+
- src/cxx_supportlib/ConfigKit/AsyncUtils.h
|
425
427
|
- src/cxx_supportlib/ConfigKit/Common.h
|
426
428
|
- src/cxx_supportlib/ConfigKit/ConfigKit.h
|
427
429
|
- src/cxx_supportlib/ConfigKit/DummyTranslator.h
|
430
|
+
- src/cxx_supportlib/ConfigKit/IN_PRACTICE.md
|
428
431
|
- src/cxx_supportlib/ConfigKit/PrefixTranslator.h
|
429
432
|
- src/cxx_supportlib/ConfigKit/README.md
|
430
433
|
- src/cxx_supportlib/ConfigKit/Schema.h
|
431
434
|
- src/cxx_supportlib/ConfigKit/Store.h
|
435
|
+
- src/cxx_supportlib/ConfigKit/SubComponentUtils.h
|
432
436
|
- src/cxx_supportlib/ConfigKit/TableTranslator.h
|
433
437
|
- src/cxx_supportlib/ConfigKit/Utils.h
|
438
|
+
- src/cxx_supportlib/ConfigKit/ValidationUtils.h
|
434
439
|
- src/cxx_supportlib/ConfigKit/VariantMapUtils.h
|
435
440
|
- src/cxx_supportlib/Constants.h
|
436
441
|
- src/cxx_supportlib/Constants.h.cxxcodebuilder
|
@@ -446,8 +451,13 @@ files:
|
|
446
451
|
- src/cxx_supportlib/Hooks.h
|
447
452
|
- src/cxx_supportlib/InstanceDirectory.h
|
448
453
|
- src/cxx_supportlib/Integrations/LibevJsonUtils.h
|
449
|
-
- src/cxx_supportlib/
|
450
|
-
- src/cxx_supportlib/
|
454
|
+
- src/cxx_supportlib/LoggingKit/Assert.h
|
455
|
+
- src/cxx_supportlib/LoggingKit/Config.h
|
456
|
+
- src/cxx_supportlib/LoggingKit/Context.h
|
457
|
+
- src/cxx_supportlib/LoggingKit/Forward.h
|
458
|
+
- src/cxx_supportlib/LoggingKit/Implementation.cpp
|
459
|
+
- src/cxx_supportlib/LoggingKit/Logging.h
|
460
|
+
- src/cxx_supportlib/LoggingKit/LoggingKit.h
|
451
461
|
- src/cxx_supportlib/LveLoggingDecorator.h
|
452
462
|
- src/cxx_supportlib/MemoryKit/mbuf.cpp
|
453
463
|
- src/cxx_supportlib/MemoryKit/mbuf.h
|
@@ -1,295 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2010-2017 Phusion Holding B.V.
|
4
|
-
*
|
5
|
-
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
|
-
* trademarks of Phusion Holding B.V.
|
7
|
-
*
|
8
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
9
|
-
* of this software and associated documentation files (the "Software"), to deal
|
10
|
-
* in the Software without restriction, including without limitation the rights
|
11
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
12
|
-
* copies of the Software, and to permit persons to whom the Software is
|
13
|
-
* furnished to do so, subject to the following conditions:
|
14
|
-
*
|
15
|
-
* The above copyright notice and this permission notice shall be included in
|
16
|
-
* all copies or substantial portions of the Software.
|
17
|
-
*
|
18
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
19
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
20
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
21
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
22
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23
|
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
24
|
-
* THE SOFTWARE.
|
25
|
-
*/
|
26
|
-
#include <iomanip>
|
27
|
-
#include <cstdlib>
|
28
|
-
#include <cstring>
|
29
|
-
#include <fcntl.h>
|
30
|
-
#include <unistd.h>
|
31
|
-
|
32
|
-
#include <boost/thread.hpp>
|
33
|
-
#include <boost/atomic.hpp>
|
34
|
-
#include <Logging.h>
|
35
|
-
#include <Constants.h>
|
36
|
-
#include <StaticString.h>
|
37
|
-
#include <Utils/StrIntUtils.h>
|
38
|
-
#include <Utils/IOUtils.h>
|
39
|
-
|
40
|
-
namespace Passenger {
|
41
|
-
|
42
|
-
volatile sig_atomic_t _logLevel = DEFAULT_LOG_LEVEL;
|
43
|
-
AssertionFailureInfo lastAssertionFailure;
|
44
|
-
static bool printAppOutputAsDebuggingMessages = false;
|
45
|
-
|
46
|
-
static boost::mutex logFileMutex;
|
47
|
-
static string logFile;
|
48
|
-
static int logFd = STDERR_FILENO;
|
49
|
-
|
50
|
-
static int fileDescriptorLog = -1;
|
51
|
-
static string fileDescriptorLogFile;
|
52
|
-
|
53
|
-
#define TRUNCATE_LOGPATHS_TO_MAXCHARS 3 // set to 0 to disable truncation
|
54
|
-
|
55
|
-
|
56
|
-
void
|
57
|
-
setLogLevel(int value) {
|
58
|
-
_logLevel = value;
|
59
|
-
boost::atomic_signal_fence(boost::memory_order_seq_cst);
|
60
|
-
}
|
61
|
-
|
62
|
-
string getLogFile() {
|
63
|
-
boost::lock_guard<boost::mutex> l(logFileMutex);
|
64
|
-
return logFile;
|
65
|
-
}
|
66
|
-
|
67
|
-
bool
|
68
|
-
setLogFile(const string &path, int *errcode) {
|
69
|
-
int fd = open(path.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0644);
|
70
|
-
if (fd != -1) {
|
71
|
-
setLogFileWithFd(path, fd);
|
72
|
-
close(fd);
|
73
|
-
return true;
|
74
|
-
} else {
|
75
|
-
if (errcode != NULL) {
|
76
|
-
*errcode = errno;
|
77
|
-
}
|
78
|
-
return false;
|
79
|
-
}
|
80
|
-
}
|
81
|
-
|
82
|
-
void
|
83
|
-
setLogFileWithFd(const string &path, int fd) {
|
84
|
-
boost::lock_guard<boost::mutex> l(logFileMutex);
|
85
|
-
dup2(fd, STDOUT_FILENO);
|
86
|
-
dup2(fd, STDERR_FILENO);
|
87
|
-
logFile = path;
|
88
|
-
}
|
89
|
-
|
90
|
-
bool
|
91
|
-
setLogFileWithoutRedirectingStderr(const string &path, int *errcode) {
|
92
|
-
int fd = open(path.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0644);
|
93
|
-
if (fd != -1) {
|
94
|
-
int oldLogFd = logFd;
|
95
|
-
logFd = fd;
|
96
|
-
if (oldLogFd != STDERR_FILENO) {
|
97
|
-
close(oldLogFd);
|
98
|
-
}
|
99
|
-
boost::lock_guard<boost::mutex> l(logFileMutex);
|
100
|
-
logFile = path;
|
101
|
-
return true;
|
102
|
-
} else {
|
103
|
-
if (errcode != NULL) {
|
104
|
-
*errcode = errno;
|
105
|
-
}
|
106
|
-
return false;
|
107
|
-
}
|
108
|
-
}
|
109
|
-
|
110
|
-
bool
|
111
|
-
hasFileDescriptorLogFile() {
|
112
|
-
return fileDescriptorLog != -1;
|
113
|
-
}
|
114
|
-
|
115
|
-
string
|
116
|
-
getFileDescriptorLogFile() {
|
117
|
-
return fileDescriptorLogFile;
|
118
|
-
}
|
119
|
-
|
120
|
-
int
|
121
|
-
getFileDescriptorLogFileFd() {
|
122
|
-
return fileDescriptorLog;
|
123
|
-
}
|
124
|
-
|
125
|
-
bool
|
126
|
-
setFileDescriptorLogFile(const string &path, int *errcode) {
|
127
|
-
int fd = open(path.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0644);
|
128
|
-
if (fd != -1) {
|
129
|
-
if (fileDescriptorLog == -1) {
|
130
|
-
fileDescriptorLog = fd;
|
131
|
-
} else {
|
132
|
-
dup2(fd, fileDescriptorLog);
|
133
|
-
close(fd);
|
134
|
-
}
|
135
|
-
if (fileDescriptorLogFile != path) {
|
136
|
-
// Do not mutate `fileDescriptorLogFile` if the path
|
137
|
-
// hasn't changed. This allows `setFileDescriptorLogFile()`
|
138
|
-
// to be thread-safe within the documented constraints.
|
139
|
-
fileDescriptorLogFile = path;
|
140
|
-
}
|
141
|
-
return true;
|
142
|
-
} else {
|
143
|
-
if (errcode != NULL) {
|
144
|
-
*errcode = errno;
|
145
|
-
}
|
146
|
-
return false;
|
147
|
-
}
|
148
|
-
}
|
149
|
-
|
150
|
-
void
|
151
|
-
_prepareLogEntry(FastStringStream<> &sstream, const char *file, unsigned int line) {
|
152
|
-
struct tm the_tm;
|
153
|
-
char datetime_buf[32];
|
154
|
-
int datetime_size;
|
155
|
-
struct timeval tv;
|
156
|
-
|
157
|
-
gettimeofday(&tv, NULL);
|
158
|
-
localtime_r(&tv.tv_sec, &the_tm);
|
159
|
-
datetime_size = snprintf(datetime_buf, sizeof(datetime_buf),
|
160
|
-
"%d-%02d-%02d %02d:%02d:%02d.%04llu",
|
161
|
-
the_tm.tm_year + 1900, the_tm.tm_mon + 1, the_tm.tm_mday,
|
162
|
-
the_tm.tm_hour, the_tm.tm_min, the_tm.tm_sec,
|
163
|
-
(unsigned long long) tv.tv_usec / 100);
|
164
|
-
sstream <<
|
165
|
-
"[ " << StaticString(datetime_buf, datetime_size) <<
|
166
|
-
" " << std::dec << getpid() << "/" <<
|
167
|
-
std::hex << pthread_self() << std::dec <<
|
168
|
-
" ";
|
169
|
-
|
170
|
-
if (startsWith(file, P_STATIC_STRING("src/"))) { // special reduncancy filter because most code resides in these paths
|
171
|
-
file += sizeof("src/") - 1;
|
172
|
-
if (startsWith(file, P_STATIC_STRING("cxx_supportlib/"))) {
|
173
|
-
file += sizeof("cxx_supportlib/") - 1;
|
174
|
-
}
|
175
|
-
}
|
176
|
-
|
177
|
-
if (TRUNCATE_LOGPATHS_TO_MAXCHARS > 0) {
|
178
|
-
truncateBeforeTokens(file, P_STATIC_STRING("/\\"), TRUNCATE_LOGPATHS_TO_MAXCHARS, sstream);
|
179
|
-
} else {
|
180
|
-
sstream << file;
|
181
|
-
}
|
182
|
-
|
183
|
-
sstream << ":" << line << " ]: ";
|
184
|
-
}
|
185
|
-
|
186
|
-
static void
|
187
|
-
writeExactWithoutOXT(int fd, const char *str, unsigned int size) {
|
188
|
-
/* We do not use writeExact() here because writeExact()
|
189
|
-
* uses oxt::syscalls::write(), which is an interruption point and
|
190
|
-
* which is slightly more expensive than a plain write().
|
191
|
-
* Logging may block, but in most cases not indefinitely,
|
192
|
-
* so we don't care if the write() here is not an interruption
|
193
|
-
* point. If the write does block indefinitely then it's
|
194
|
-
* probably a FIFO that is not opened on the other side.
|
195
|
-
* In that case we can blame the user.
|
196
|
-
*/
|
197
|
-
ssize_t ret;
|
198
|
-
unsigned int written = 0;
|
199
|
-
while (written < size) {
|
200
|
-
do {
|
201
|
-
ret = write(fd, str + written, size - written);
|
202
|
-
} while (ret == -1 && errno == EINTR);
|
203
|
-
if (ret == -1) {
|
204
|
-
/* The most likely reason why this fails is when the user has setup
|
205
|
-
* Apache to log to a pipe (e.g. to a log rotation script). Upon
|
206
|
-
* restarting the web server, the process that reads from the pipe
|
207
|
-
* shuts down, so we can't write to it anymore. That's why we
|
208
|
-
* just ignore write errors. It doesn't make sense to abort for
|
209
|
-
* something like this.
|
210
|
-
*/
|
211
|
-
break;
|
212
|
-
} else {
|
213
|
-
written += ret;
|
214
|
-
}
|
215
|
-
}
|
216
|
-
}
|
217
|
-
|
218
|
-
void
|
219
|
-
_writeLogEntry(const char *str, unsigned int size) {
|
220
|
-
writeExactWithoutOXT(logFd, str, size);
|
221
|
-
}
|
222
|
-
|
223
|
-
void
|
224
|
-
_writeFileDescriptorLogEntry(const char *str, unsigned int size) {
|
225
|
-
writeExactWithoutOXT(fileDescriptorLog, str, size);
|
226
|
-
}
|
227
|
-
|
228
|
-
const char *
|
229
|
-
_strdupFastStringStream(const FastStringStream<> &stream) {
|
230
|
-
char *buf = (char *) malloc(stream.size() + 1);
|
231
|
-
memcpy(buf, stream.data(), stream.size());
|
232
|
-
buf[stream.size()] = '\0';
|
233
|
-
return buf;
|
234
|
-
}
|
235
|
-
|
236
|
-
static void
|
237
|
-
realPrintAppOutput(char *buf, unsigned int bufSize,
|
238
|
-
const char *pidStr, unsigned int pidStrLen,
|
239
|
-
const char *channelName, unsigned int channelNameLen,
|
240
|
-
const char *message, unsigned int messageLen)
|
241
|
-
{
|
242
|
-
char *pos = buf;
|
243
|
-
char *end = buf + bufSize;
|
244
|
-
|
245
|
-
pos = appendData(pos, end, "App ");
|
246
|
-
pos = appendData(pos, end, pidStr, pidStrLen);
|
247
|
-
pos = appendData(pos, end, " ");
|
248
|
-
pos = appendData(pos, end, channelName, channelNameLen);
|
249
|
-
pos = appendData(pos, end, ": ");
|
250
|
-
pos = appendData(pos, end, message, messageLen);
|
251
|
-
pos = appendData(pos, end, "\n");
|
252
|
-
_writeLogEntry(buf, pos - buf);
|
253
|
-
}
|
254
|
-
|
255
|
-
void
|
256
|
-
printAppOutput(pid_t pid, const char *channelName, const char *message, unsigned int size) {
|
257
|
-
if (printAppOutputAsDebuggingMessages) {
|
258
|
-
P_DEBUG("App " << pid << " " << channelName << ": " << StaticString(message, size));
|
259
|
-
} else {
|
260
|
-
char pidStr[sizeof("4294967295")];
|
261
|
-
unsigned int pidStrLen, channelNameLen, totalLen;
|
262
|
-
|
263
|
-
try {
|
264
|
-
pidStrLen = integerToOtherBase<pid_t, 10>(pid, pidStr, sizeof(pidStr));
|
265
|
-
} catch (const std::length_error &) {
|
266
|
-
pidStr[0] = '?';
|
267
|
-
pidStr[1] = '\0';
|
268
|
-
pidStrLen = 1;
|
269
|
-
}
|
270
|
-
|
271
|
-
channelNameLen = strlen(channelName);
|
272
|
-
totalLen = (sizeof("App X Y: \n") - 2) + pidStrLen + channelNameLen + size;
|
273
|
-
if (totalLen < 1024) {
|
274
|
-
char buf[1024];
|
275
|
-
realPrintAppOutput(buf, sizeof(buf),
|
276
|
-
pidStr, pidStrLen,
|
277
|
-
channelName, channelNameLen,
|
278
|
-
message, size);
|
279
|
-
} else {
|
280
|
-
DynamicBuffer buf(totalLen);
|
281
|
-
realPrintAppOutput(buf.data, totalLen,
|
282
|
-
pidStr, pidStrLen,
|
283
|
-
channelName, channelNameLen,
|
284
|
-
message, size);
|
285
|
-
}
|
286
|
-
}
|
287
|
-
}
|
288
|
-
|
289
|
-
void
|
290
|
-
setPrintAppOutputAsDebuggingMessages(bool enabled) {
|
291
|
-
printAppOutputAsDebuggingMessages = enabled;
|
292
|
-
}
|
293
|
-
|
294
|
-
} // namespace Passenger
|
295
|
-
|
@@ -1,385 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2010-2017 Phusion Holding B.V.
|
4
|
-
*
|
5
|
-
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
|
-
* trademarks of Phusion Holding B.V.
|
7
|
-
*
|
8
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
9
|
-
* of this software and associated documentation files (the "Software"), to deal
|
10
|
-
* in the Software without restriction, including without limitation the rights
|
11
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
12
|
-
* copies of the Software, and to permit persons to whom the Software is
|
13
|
-
* furnished to do so, subject to the following conditions:
|
14
|
-
*
|
15
|
-
* The above copyright notice and this permission notice shall be included in
|
16
|
-
* all copies or substantial portions of the Software.
|
17
|
-
*
|
18
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
19
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
20
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
21
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
22
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23
|
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
24
|
-
* THE SOFTWARE.
|
25
|
-
*/
|
26
|
-
#ifndef _PASSENGER_LOGGING_H_
|
27
|
-
#define _PASSENGER_LOGGING_H_
|
28
|
-
|
29
|
-
#include <oxt/thread.hpp>
|
30
|
-
#include <oxt/system_calls.hpp>
|
31
|
-
#include <oxt/macros.hpp>
|
32
|
-
|
33
|
-
#include <sys/types.h>
|
34
|
-
#include <sys/time.h>
|
35
|
-
#include <sys/file.h>
|
36
|
-
#include <sys/resource.h>
|
37
|
-
#include <unistd.h>
|
38
|
-
#include <fcntl.h>
|
39
|
-
#include <pthread.h>
|
40
|
-
#include <string>
|
41
|
-
#include <exception>
|
42
|
-
#include <stdexcept>
|
43
|
-
#include <ios>
|
44
|
-
#include <ostream>
|
45
|
-
#include <sstream>
|
46
|
-
#include <cstdio>
|
47
|
-
#include <ctime>
|
48
|
-
#include <cerrno>
|
49
|
-
#include <csignal>
|
50
|
-
#include <Utils/FastStringStream.h>
|
51
|
-
|
52
|
-
|
53
|
-
namespace Passenger {
|
54
|
-
|
55
|
-
using namespace std;
|
56
|
-
using namespace boost;
|
57
|
-
using namespace oxt;
|
58
|
-
|
59
|
-
|
60
|
-
struct AssertionFailureInfo {
|
61
|
-
const char *filename;
|
62
|
-
const char *function; // May be NULL.
|
63
|
-
const char *expression;
|
64
|
-
unsigned int line;
|
65
|
-
};
|
66
|
-
|
67
|
-
extern volatile sig_atomic_t _logLevel;
|
68
|
-
// If assert() or similar fails, we attempt to store its information here.
|
69
|
-
extern AssertionFailureInfo lastAssertionFailure;
|
70
|
-
|
71
|
-
/**
|
72
|
-
* Returns the current log level. This method is thread-safe.
|
73
|
-
*/
|
74
|
-
inline OXT_FORCE_INLINE int
|
75
|
-
getLogLevel() {
|
76
|
-
return (int) _logLevel;
|
77
|
-
}
|
78
|
-
|
79
|
-
/**
|
80
|
-
* Sets the log level. This method is thread-safe.
|
81
|
-
*/
|
82
|
-
void setLogLevel(int value);
|
83
|
-
|
84
|
-
/**
|
85
|
-
* Returns the general log file that we're using, or the empty string
|
86
|
-
* if we're not using a log file.
|
87
|
-
*
|
88
|
-
* This method is thread-safe.
|
89
|
-
*/
|
90
|
-
string getLogFile();
|
91
|
-
|
92
|
-
/**
|
93
|
-
* Sets the general log file. This method is thread-safe.
|
94
|
-
* Returns whether the new log file can be opened. If not,
|
95
|
-
* `errcode` (if non-NULL) is set to the relevant filesystem
|
96
|
-
* error code.
|
97
|
-
*/
|
98
|
-
bool setLogFile(const string &path, int *errcode = NULL);
|
99
|
-
|
100
|
-
/**
|
101
|
-
* Sets the general log file, assuming that it's already opened
|
102
|
-
* at the given fd. This method is thread-safe.
|
103
|
-
*/
|
104
|
-
void setLogFileWithFd(const string &path, int fd);
|
105
|
-
|
106
|
-
/**
|
107
|
-
* Sets the general log file. Unlike `setLogFile()` and `setLogFileWithFd()`,
|
108
|
-
* this method does not redirect stderr to that file. This is useful in
|
109
|
-
* e.g. the Apache module where redirecting stderr is not safe because it
|
110
|
-
* would affect all the other Apache modules too.
|
111
|
-
*
|
112
|
-
* Returns whether the new log file can be opened. If not,
|
113
|
-
* `errcode` (if non-NULL) is set to the relevant filesystem
|
114
|
-
* error code.
|
115
|
-
*
|
116
|
-
* WARNING:
|
117
|
-
* This method is NOT thread-safe.
|
118
|
-
* Once you have called this method, you may not call `setLogFile()`
|
119
|
-
* or `setLogFileWithFd()`.
|
120
|
-
*/
|
121
|
-
bool setLogFileWithoutRedirectingStderr(const string &path, int *errcode = NULL);
|
122
|
-
|
123
|
-
/**
|
124
|
-
* Returns whether we're using a separate log file for logging file
|
125
|
-
* descriptor opening and closing.
|
126
|
-
*
|
127
|
-
* See `getFileDescriptorLogFile()` for thread-safety notes.
|
128
|
-
*/
|
129
|
-
bool hasFileDescriptorLogFile();
|
130
|
-
|
131
|
-
/**
|
132
|
-
* Returns the file that we're using for logging file descriptor
|
133
|
-
* opening and closing, or the empty string if we're not using a
|
134
|
-
* separate log file.
|
135
|
-
*
|
136
|
-
* This method is only thread-safe if `setFileDescriptorLogFile()`
|
137
|
-
* was called before any threads were made, and at the same time
|
138
|
-
* `setFileDescriptorLogFile()` is never called again with a different
|
139
|
-
* argument. In other words, only reopening the same log file is
|
140
|
-
* thread-safe.
|
141
|
-
*/
|
142
|
-
string getFileDescriptorLogFile();
|
143
|
-
|
144
|
-
/**
|
145
|
-
* Returns the file descriptor of the log file that we're using for
|
146
|
-
* logging file descriptor opening and closing, or -1 if we're not using a
|
147
|
-
* separate log file.
|
148
|
-
*
|
149
|
-
* See `getFileDescriptorLogFile()` for thread-safety notes.
|
150
|
-
*/
|
151
|
-
int getFileDescriptorLogFileFd();
|
152
|
-
|
153
|
-
/**
|
154
|
-
* Sets the log file to use specifically for logging file descriptor
|
155
|
-
* opening and closing.
|
156
|
-
*
|
157
|
-
* This method is only thread-safe if you `path` equals what
|
158
|
-
* `getFileDescriptorLogFile()` returns. In other words, when
|
159
|
-
* you're reopening the log file.
|
160
|
-
*
|
161
|
-
* Returns whether the new log file can be opened. If not,
|
162
|
-
* errcode (if non-NULL) is set to the relevant filesystem
|
163
|
-
* error code.
|
164
|
-
*/
|
165
|
-
bool setFileDescriptorLogFile(const string &path, int *errcode = NULL);
|
166
|
-
|
167
|
-
void _prepareLogEntry(FastStringStream<> &sstream, const char *file, unsigned int line);
|
168
|
-
void _writeLogEntry(const char *str, unsigned int size);
|
169
|
-
void _writeFileDescriptorLogEntry(const char *str, unsigned int size);
|
170
|
-
const char *_strdupFastStringStream(const FastStringStream<> &stream);
|
171
|
-
|
172
|
-
|
173
|
-
enum PassengerLogLevel {
|
174
|
-
LVL_CRIT = 0,
|
175
|
-
LVL_ERROR = 1,
|
176
|
-
LVL_WARN = 2,
|
177
|
-
LVL_NOTICE = 3,
|
178
|
-
LVL_INFO = 4,
|
179
|
-
LVL_DEBUG = 5,
|
180
|
-
LVL_DEBUG2 = 6,
|
181
|
-
LVL_DEBUG3 = 7
|
182
|
-
};
|
183
|
-
|
184
|
-
/**
|
185
|
-
* Write the given expression to the log stream.
|
186
|
-
*/
|
187
|
-
#define P_LOG(level, file, line, expr) \
|
188
|
-
do { \
|
189
|
-
if (Passenger::getLogLevel() >= (level)) { \
|
190
|
-
Passenger::FastStringStream<> _ostream; \
|
191
|
-
Passenger::_prepareLogEntry(_ostream, file, line); \
|
192
|
-
_ostream << expr << "\n"; \
|
193
|
-
Passenger::_writeLogEntry(_ostream.data(), _ostream.size()); \
|
194
|
-
} \
|
195
|
-
} while (false)
|
196
|
-
|
197
|
-
#define P_LOG_UNLIKELY(level, file, line, expr) \
|
198
|
-
do { \
|
199
|
-
if (OXT_UNLIKELY(Passenger::getLogLevel() >= (level))) { \
|
200
|
-
Passenger::FastStringStream<> _ostream; \
|
201
|
-
Passenger::_prepareLogEntry(_ostream, file, line); \
|
202
|
-
_ostream << expr << "\n"; \
|
203
|
-
Passenger::_writeLogEntry(_ostream.data(), _ostream.size()); \
|
204
|
-
} \
|
205
|
-
} while (false)
|
206
|
-
|
207
|
-
/**
|
208
|
-
* Write the given expression, which represents a warning,
|
209
|
-
* to the log stream.
|
210
|
-
*/
|
211
|
-
#define P_WARN(expr) P_LOG(LVL_WARN, __FILE__, __LINE__, expr)
|
212
|
-
#define P_WARN_WITH_POS(file, line, expr) P_LOG(LVL_WARN, file, line, expr)
|
213
|
-
|
214
|
-
/**
|
215
|
-
* Write the given expression, which represents a notice (important information),
|
216
|
-
* to the log stream.
|
217
|
-
*/
|
218
|
-
#define P_NOTICE(expr) P_LOG(LVL_NOTICE, __FILE__, __LINE__, expr)
|
219
|
-
#define P_NOTICE_WITH_POS(file, line, expr) P_LOG(LVL_NOTICE, file, line, expr)
|
220
|
-
|
221
|
-
/**
|
222
|
-
* Write the given expression, which represents a normal information message,
|
223
|
-
* to the log stream.
|
224
|
-
*/
|
225
|
-
#define P_INFO(expr) P_LOG(LVL_INFO, __FILE__, __LINE__, expr)
|
226
|
-
#define P_INFO_WITH_POS(file, line, expr) P_LOG(LVL_INFO, file, line, expr)
|
227
|
-
|
228
|
-
/**
|
229
|
-
* Write the given expression, which represents an error,
|
230
|
-
* to the log stream.
|
231
|
-
*/
|
232
|
-
#define P_ERROR(expr) P_LOG(LVL_ERROR, __FILE__, __LINE__, expr)
|
233
|
-
#define P_ERROR_WITH_POS(file, line, expr) P_LOG(LVL_ERROR, file, line, expr)
|
234
|
-
|
235
|
-
/**
|
236
|
-
* Write the given expression, which represents a critical non-recoverable error,
|
237
|
-
* to the log stream.
|
238
|
-
*/
|
239
|
-
#define P_CRITICAL(expr) P_LOG(LVL_CRIT, __FILE__, __LINE__, expr)
|
240
|
-
#define P_CRITICAL_WITH_POS(expr, file, line) P_LOG(LVL_CRIT, file, line, expr)
|
241
|
-
|
242
|
-
/**
|
243
|
-
* Write the given expression, which represents a debugging message,
|
244
|
-
* to the log stream.
|
245
|
-
*/
|
246
|
-
#define P_DEBUG(expr) P_TRACE(1, expr)
|
247
|
-
#define P_DEBUG_WITH_POS(file, line, expr) P_TRACE_WITH_POS(1, file, line, expr)
|
248
|
-
|
249
|
-
#ifdef PASSENGER_DEBUG
|
250
|
-
#define P_TRACE(level, expr) P_LOG_UNLIKELY(LVL_INFO + level, __FILE__, __LINE__, expr)
|
251
|
-
#define P_TRACE_WITH_POS(level, file, line, expr) P_LOG_UNLIKELY(LVL_INFO + level, file, line, expr)
|
252
|
-
#else
|
253
|
-
#define P_TRACE(level, expr) do { /* nothing */ } while (false)
|
254
|
-
#define P_TRACE_WITH_POS(level, file, line, expr) do { /* nothing */ } while (false)
|
255
|
-
#endif
|
256
|
-
|
257
|
-
|
258
|
-
/**
|
259
|
-
* Log the fact that a file descriptor has been opened.
|
260
|
-
*/
|
261
|
-
#define P_LOG_FILE_DESCRIPTOR_OPEN(fd) \
|
262
|
-
P_LOG_FILE_DESCRIPTOR_OPEN3(fd, __FILE__, __LINE__)
|
263
|
-
#define P_LOG_FILE_DESCRIPTOR_OPEN2(fd, expr) \
|
264
|
-
P_LOG_FILE_DESCRIPTOR_OPEN4(fd, __FILE__, __LINE__, expr)
|
265
|
-
#define P_LOG_FILE_DESCRIPTOR_OPEN3(fd, file, line) \
|
266
|
-
do { \
|
267
|
-
if (Passenger::hasFileDescriptorLogFile() || Passenger::getLogLevel() >= Passenger::LVL_DEBUG) { \
|
268
|
-
Passenger::FastStringStream<> _ostream; \
|
269
|
-
Passenger::_prepareLogEntry(_ostream, file, line); \
|
270
|
-
_ostream << "File descriptor opened: " << fd << "\n"; \
|
271
|
-
if (hasFileDescriptorLogFile()) { \
|
272
|
-
Passenger::_writeFileDescriptorLogEntry(_ostream.data(), _ostream.size()); \
|
273
|
-
} else { \
|
274
|
-
Passenger::_writeLogEntry(_ostream.data(), _ostream.size()); \
|
275
|
-
} \
|
276
|
-
} \
|
277
|
-
} while (false)
|
278
|
-
#define P_LOG_FILE_DESCRIPTOR_OPEN4(fd, file, line, expr) \
|
279
|
-
do { \
|
280
|
-
P_LOG_FILE_DESCRIPTOR_OPEN3(fd, file, line); \
|
281
|
-
P_LOG_FILE_DESCRIPTOR_PURPOSE(fd, expr); \
|
282
|
-
} while (false)
|
283
|
-
|
284
|
-
/**
|
285
|
-
* Log the purpose of a file descriptor that was recently logged with
|
286
|
-
* P_LOG_FILE_DESCRIPTOR_OPEN(). You should include information that
|
287
|
-
* allows a reader to find out what a file descriptor is for.
|
288
|
-
*/
|
289
|
-
#define P_LOG_FILE_DESCRIPTOR_PURPOSE(fd, expr) \
|
290
|
-
do { \
|
291
|
-
if (Passenger::hasFileDescriptorLogFile() || Passenger::getLogLevel() >= Passenger::LVL_DEBUG) { \
|
292
|
-
Passenger::FastStringStream<> _ostream; \
|
293
|
-
Passenger::_prepareLogEntry(_ostream, __FILE__, __LINE__); \
|
294
|
-
_ostream << "File descriptor purpose: " << fd << ": " << expr << "\n"; \
|
295
|
-
if (hasFileDescriptorLogFile()) { \
|
296
|
-
Passenger::_writeFileDescriptorLogEntry(_ostream.data(), _ostream.size()); \
|
297
|
-
} else { \
|
298
|
-
Passenger::_writeLogEntry(_ostream.data(), _ostream.size()); \
|
299
|
-
} \
|
300
|
-
} \
|
301
|
-
} while (false)
|
302
|
-
|
303
|
-
/**
|
304
|
-
* Log the fact that a file descriptor has been closed.
|
305
|
-
*/
|
306
|
-
#define P_LOG_FILE_DESCRIPTOR_CLOSE(fd) \
|
307
|
-
do { \
|
308
|
-
if (Passenger::hasFileDescriptorLogFile() || Passenger::getLogLevel() >= Passenger::LVL_DEBUG) { \
|
309
|
-
Passenger::FastStringStream<> _ostream; \
|
310
|
-
Passenger::_prepareLogEntry(_ostream, __FILE__, __LINE__); \
|
311
|
-
_ostream << "File descriptor closed: " << fd << "\n"; \
|
312
|
-
if (hasFileDescriptorLogFile()) { \
|
313
|
-
Passenger::_writeFileDescriptorLogEntry(_ostream.data(), _ostream.size()); \
|
314
|
-
} else { \
|
315
|
-
Passenger::_writeLogEntry(_ostream.data(), _ostream.size()); \
|
316
|
-
} \
|
317
|
-
} \
|
318
|
-
} while (false)
|
319
|
-
|
320
|
-
/**
|
321
|
-
* Print a message that was received from an application's stdout/stderr.
|
322
|
-
*
|
323
|
-
* @param pid The application's PID.
|
324
|
-
* @param channelName "stdout" or "stderr".
|
325
|
-
* @param message The message that was received.
|
326
|
-
*/
|
327
|
-
void printAppOutput(pid_t pid, const char *channelName, const char *message, unsigned int size);
|
328
|
-
|
329
|
-
/**
|
330
|
-
* Controls how messages that are received from applications are printed.
|
331
|
-
*
|
332
|
-
* If `enabled` is true then messages are printed using P_DEBUG, meaning that
|
333
|
-
* the normal Passenger logging prefixes will be printed as well.
|
334
|
-
*
|
335
|
-
* If `enabled` is false (the default), then messages are printed directly
|
336
|
-
* to the log output channel using write(), with only a very short prefix
|
337
|
-
* that contains the PID and channel name.
|
338
|
-
*/
|
339
|
-
void setPrintAppOutputAsDebuggingMessages(bool enabled);
|
340
|
-
|
341
|
-
/** Print a [BUG] error message and abort with a stack trace. */
|
342
|
-
#define P_BUG_WITH_FORMATTER_CODE(varname, code) \
|
343
|
-
do { \
|
344
|
-
TRACE_POINT(); \
|
345
|
-
const char *_exprStr; \
|
346
|
-
Passenger::FastStringStream<> varname; \
|
347
|
-
code \
|
348
|
-
_exprStr = Passenger::_strdupFastStringStream(varname); \
|
349
|
-
Passenger::lastAssertionFailure.filename = __FILE__; \
|
350
|
-
Passenger::lastAssertionFailure.line = __LINE__; \
|
351
|
-
Passenger::lastAssertionFailure.function = __PRETTY_FUNCTION__; \
|
352
|
-
Passenger::lastAssertionFailure.expression = _exprStr; \
|
353
|
-
P_CRITICAL("[BUG] " << _exprStr); \
|
354
|
-
abort(); \
|
355
|
-
} while (false)
|
356
|
-
|
357
|
-
#define P_BUG_UTP_WITH_FORMATTER_CODE(varname, code) \
|
358
|
-
do { \
|
359
|
-
UPDATE_TRACE_POINT(); \
|
360
|
-
const char *_exprStr; \
|
361
|
-
Passenger::FastStringStream<> varname; \
|
362
|
-
code \
|
363
|
-
_exprStr = Passenger::_strdupFastStringStream(varname); \
|
364
|
-
Passenger::lastAssertionFailure.filename = __FILE__; \
|
365
|
-
Passenger::lastAssertionFailure.line = __LINE__; \
|
366
|
-
Passenger::lastAssertionFailure.function = __PRETTY_FUNCTION__; \
|
367
|
-
Passenger::lastAssertionFailure.expression = _exprStr; \
|
368
|
-
P_CRITICAL("[BUG] " << _exprStr); \
|
369
|
-
abort(); \
|
370
|
-
} while (false)
|
371
|
-
|
372
|
-
#define P_BUG(expr) P_BUG_WITH_FORMATTER_CODE( _sstream , _sstream << expr; )
|
373
|
-
#define P_BUG_UTP(expr) P_BUG_UTP_WITH_FORMATTER_CODE( _sstream , _sstream << expr; )
|
374
|
-
|
375
|
-
#define P_ASSERT_EQ(value, expected) \
|
376
|
-
do { \
|
377
|
-
if (OXT_UNLIKELY(value != expected)) { \
|
378
|
-
P_BUG("Expected " << #value << " to be " << expected << ", got " << value); \
|
379
|
-
} \
|
380
|
-
} while (false)
|
381
|
-
|
382
|
-
|
383
|
-
} // namespace Passenger
|
384
|
-
|
385
|
-
#endif /* _PASSENGER_LOGGING_H_ */
|