passenger 4.0.17 → 4.0.18
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- data.tar.gz.asc +7 -7
- data/NEWS +21 -0
- data/bin/passenger +2 -0
- data/bin/passenger-config +2 -0
- data/bin/passenger-install-apache2-module +2 -0
- data/bin/passenger-install-nginx-module +2 -0
- data/bin/passenger-memory-stats +2 -0
- data/bin/passenger-status +2 -0
- data/build/debian.rb +3 -1
- data/build/packaging.rb +42 -2
- data/build/preprocessor.rb +7 -0
- data/debian.template/control.template +9 -3
- data/debian.template/rules.template +2 -1
- data/doc/Users guide Apache.idmap.txt +5 -1
- data/doc/Users guide Nginx.idmap.txt +5 -1
- data/doc/users_guide_snippets/installation.txt +71 -64
- data/ext/apache2/Hooks.cpp +17 -1
- data/ext/common/ApplicationPool2/Process.h +38 -2
- data/ext/common/Constants.h +5 -1
- data/ext/common/EventedClient.h +22 -1
- data/ext/common/EventedMessageServer.h +15 -0
- data/ext/common/UnionStation.h +2 -2
- data/ext/common/agents/HelperAgent/RequestHandler.h +24 -9
- data/ext/common/agents/LoggingAgent/LoggingServer.h +24 -11
- data/ext/oxt/backtrace.hpp +4 -6
- data/ext/oxt/detail/backtrace_disabled.hpp +1 -0
- data/ext/oxt/detail/backtrace_enabled.hpp +10 -4
- data/ext/oxt/detail/context.hpp +1 -0
- data/ext/oxt/implementation.cpp +21 -7
- data/helper-scripts/download_binaries/extconf.rb +1 -1
- data/lib/phusion_passenger.rb +1 -1
- data/lib/phusion_passenger/analytics_logger.rb +3 -3
- data/lib/phusion_passenger/constants.rb +2 -0
- data/lib/phusion_passenger/packaging.rb +16 -0
- data/lib/phusion_passenger/standalone/command.rb +3 -0
- data/lib/phusion_passenger/standalone/start_command.rb +40 -2
- data/resources/templates/standalone/config.erb +3 -0
- data/test/cxx/UnionStationTest.cpp +11 -11
- data/test/ruby/analytics_logger_spec.rb +1 -1
- metadata +2 -2
- metadata.gz.asc +7 -7
data/ext/apache2/Hooks.cpp
CHANGED
@@ -45,7 +45,10 @@
|
|
45
45
|
#include <cstdio>
|
46
46
|
#include <unistd.h>
|
47
47
|
|
48
|
+
#include <oxt/initialize.hpp>
|
48
49
|
#include <oxt/macros.hpp>
|
50
|
+
#include <oxt/backtrace.hpp>
|
51
|
+
#include <oxt/detail/context.hpp>
|
49
52
|
#include "Hooks.h"
|
50
53
|
#include "Bucket.h"
|
51
54
|
#include "Configuration.hpp"
|
@@ -480,6 +483,17 @@ private:
|
|
480
483
|
int handleRequest(request_rec *r) {
|
481
484
|
/********** Step 1: preparation work **********/
|
482
485
|
|
486
|
+
/* Initialize OXT backtrace support if not already done for this thread */
|
487
|
+
if (oxt::get_thread_local_context() == NULL) {
|
488
|
+
/* There is no need to cleanup the context. Apache uses a static
|
489
|
+
* number of threads per process.
|
490
|
+
*/
|
491
|
+
thread_local_context_ptr context = thread_local_context::make_shared_ptr();
|
492
|
+
unsigned long tid = (unsigned long) pthread_self();
|
493
|
+
context->thread_name = "Worker " + integerToHex(tid);
|
494
|
+
oxt::set_thread_local_context(context);
|
495
|
+
}
|
496
|
+
|
483
497
|
/* Check whether an error occured in prepareRequest() that should be reported
|
484
498
|
* to the browser.
|
485
499
|
*/
|
@@ -1583,7 +1597,9 @@ init_module(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *
|
|
1583
1597
|
* universal, i.e. it works for some people but not for others. So we got rid of the
|
1584
1598
|
* hacks, and now we always initialize in the post_config hook.
|
1585
1599
|
*/
|
1586
|
-
if (hooks
|
1600
|
+
if (hooks == NULL) {
|
1601
|
+
oxt::initialize();
|
1602
|
+
} else {
|
1587
1603
|
P_DEBUG("Restarting Phusion Passenger....");
|
1588
1604
|
delete hooks;
|
1589
1605
|
hooks = NULL;
|
@@ -147,6 +147,34 @@ private:
|
|
147
147
|
/** The handle inside the associated Group's process priority queue. */
|
148
148
|
PriorityQueue<Process>::Handle pqHandle;
|
149
149
|
|
150
|
+
static bool
|
151
|
+
isZombie(pid_t pid) {
|
152
|
+
string filename = "/proc/" + toString(pid) + "/status";
|
153
|
+
FILE *f = fopen(filename.c_str(), "r");
|
154
|
+
if (f == NULL) {
|
155
|
+
// Don't know.
|
156
|
+
return false;
|
157
|
+
}
|
158
|
+
|
159
|
+
bool result = false;
|
160
|
+
while (!feof(f)) {
|
161
|
+
char buf[512];
|
162
|
+
const char *line;
|
163
|
+
|
164
|
+
line = fgets(buf, sizeof(buf), f);
|
165
|
+
if (line == NULL) {
|
166
|
+
break;
|
167
|
+
}
|
168
|
+
if (strcmp(line, "State: Z (zombie)\n") == 0) {
|
169
|
+
// Is a zombie.
|
170
|
+
result = true;
|
171
|
+
break;
|
172
|
+
}
|
173
|
+
}
|
174
|
+
fclose(f);
|
175
|
+
return result;
|
176
|
+
}
|
177
|
+
|
150
178
|
void indexSessionSockets() {
|
151
179
|
SocketList::iterator it;
|
152
180
|
concurrency = 0;
|
@@ -458,8 +486,16 @@ public:
|
|
458
486
|
*/
|
459
487
|
bool osProcessExists() const {
|
460
488
|
if (!dummy && m_osProcessExists) {
|
461
|
-
|
462
|
-
|
489
|
+
if (syscalls::kill(pid, 0) == 0) {
|
490
|
+
/* On some environments, e.g. Heroku, the init process does
|
491
|
+
* not properly reap adopted zombie processes, which can interfere
|
492
|
+
* with our process existance check. To work around this, we
|
493
|
+
* explicitly check whether or not the process has become a zombie.
|
494
|
+
*/
|
495
|
+
m_osProcessExists = !isZombie(pid);
|
496
|
+
} else {
|
497
|
+
m_osProcessExists = errno != ESRCH;
|
498
|
+
}
|
463
499
|
return m_osProcessExists;
|
464
500
|
} else {
|
465
501
|
return false;
|
data/ext/common/Constants.h
CHANGED
@@ -42,6 +42,8 @@
|
|
42
42
|
|
43
43
|
#define DEFAULT_ANALYTICS_LOG_USER "nobody"
|
44
44
|
|
45
|
+
#define DEFAULT_CONCURRENCY_MODEL "process"
|
46
|
+
|
45
47
|
#define DEFAULT_LOG_LEVEL 0
|
46
48
|
|
47
49
|
#define DEFAULT_MAX_INSTANCES_PER_APP 0
|
@@ -56,6 +58,8 @@
|
|
56
58
|
|
57
59
|
#define DEFAULT_START_TIMEOUT 90000
|
58
60
|
|
61
|
+
#define DEFAULT_THREAD_COUNT 1
|
62
|
+
|
59
63
|
#define DEFAULT_UNION_STATION_GATEWAY_ADDRESS "gateway.unionstationapp.com"
|
60
64
|
|
61
65
|
#define DEFAULT_UNION_STATION_GATEWAY_PORT 443
|
@@ -68,7 +72,7 @@
|
|
68
72
|
|
69
73
|
#define MESSAGE_SERVER_MAX_USERNAME_SIZE 100
|
70
74
|
|
71
|
-
#define PASSENGER_VERSION "4.0.
|
75
|
+
#define PASSENGER_VERSION "4.0.18"
|
72
76
|
|
73
77
|
#define POOL_HELPER_THREAD_STACK_SIZE 262144
|
74
78
|
|
data/ext/common/EventedClient.h
CHANGED
@@ -108,7 +108,7 @@ public:
|
|
108
108
|
typedef void (*Callback)(EventedClient *client);
|
109
109
|
typedef void (*SystemErrorCallback)(EventedClient *client, const string &message, int code);
|
110
110
|
|
111
|
-
|
111
|
+
protected:
|
112
112
|
enum {
|
113
113
|
/**
|
114
114
|
* This is the initial state for a client. It means we're
|
@@ -694,6 +694,27 @@ public:
|
|
694
694
|
return oldFd;
|
695
695
|
}
|
696
696
|
}
|
697
|
+
|
698
|
+
const char *getStateName() const {
|
699
|
+
switch (state) {
|
700
|
+
case EC_CONNECTED:
|
701
|
+
return "EC_CONNECTED";
|
702
|
+
case EC_WRITES_PENDING:
|
703
|
+
return "EC_WRITES_PENDING";
|
704
|
+
case EC_TOO_MANY_WRITES_PENDING:
|
705
|
+
return "EC_TOO_MANY_WRITES_PENDING";
|
706
|
+
case EC_RO_CONNECTED:
|
707
|
+
return "EC_RO_CONNECTED";
|
708
|
+
case EC_RO_CONNECTED_WITH_WRITES_PENDING:
|
709
|
+
return "EC_RO_CONNECTED_WITH_WRITES_PENDING";
|
710
|
+
case EC_DISCONNECTING_WITH_WRITES_PENDING:
|
711
|
+
return "EC_DISCONNECTING_WITH_WRITES_PENDING";
|
712
|
+
case EC_DISCONNECTED:
|
713
|
+
return "EC_DISCONNECTED";
|
714
|
+
default:
|
715
|
+
return "unknown";
|
716
|
+
}
|
717
|
+
}
|
697
718
|
};
|
698
719
|
|
699
720
|
|
@@ -67,6 +67,21 @@ struct EventedMessageClientContext {
|
|
67
67
|
* it's properly zeroed out. */
|
68
68
|
scalarReader.reset(true);
|
69
69
|
}
|
70
|
+
|
71
|
+
const char *getStateName() const {
|
72
|
+
switch (state) {
|
73
|
+
case MS_READING_USERNAME:
|
74
|
+
return "MS_READING_USERNAME";
|
75
|
+
case MS_READING_PASSWORD:
|
76
|
+
return "MS_READING_PASSWORD";
|
77
|
+
case MS_READING_MESSAGE:
|
78
|
+
return "MS_READING_MESSAGE";
|
79
|
+
case MS_PROCESSING_MESSAGE:
|
80
|
+
return "MS_PROCESSING_MESSAGE";
|
81
|
+
default:
|
82
|
+
return "unknown";
|
83
|
+
}
|
84
|
+
}
|
70
85
|
};
|
71
86
|
|
72
87
|
class EventedMessageClient: public EventedClient {
|
data/ext/common/UnionStation.h
CHANGED
@@ -720,7 +720,7 @@ public:
|
|
720
720
|
|
721
721
|
LoggerPtr newTransaction(const string &groupName,
|
722
722
|
const string &category = "requests",
|
723
|
-
const string &unionStationKey =
|
723
|
+
const string &unionStationKey = "-",
|
724
724
|
const string &filters = string())
|
725
725
|
{
|
726
726
|
if (serverAddress.empty()) {
|
@@ -851,7 +851,7 @@ public:
|
|
851
851
|
LoggerPtr continueTransaction(const string &txnId,
|
852
852
|
const string &groupName,
|
853
853
|
const string &category = "requests",
|
854
|
-
const string &unionStationKey =
|
854
|
+
const string &unionStationKey = "-")
|
855
855
|
{
|
856
856
|
if (serverAddress.empty() || txnId.empty()) {
|
857
857
|
return createNullLogger();
|
@@ -125,6 +125,12 @@ class RequestHandler;
|
|
125
125
|
#define RH_DEBUG(client, x) P_DEBUG("[Client " << client->name() << "] " << x)
|
126
126
|
#define RH_TRACE(client, level, x) P_TRACE(level, "[Client " << client->name() << "] " << x)
|
127
127
|
|
128
|
+
#define RH_LOG_EVENT(client, eventName) \
|
129
|
+
char _clientName[7 + 8]; \
|
130
|
+
snprintf(_clientName, sizeof(_clientName), "Client %d", client->fdnum); \
|
131
|
+
TRACE_POINT_WITH_DATA(_clientName); \
|
132
|
+
RH_TRACE(client, 3, "Event: " eventName)
|
133
|
+
|
128
134
|
|
129
135
|
class Client: public enable_shared_from_this<Client> {
|
130
136
|
private:
|
@@ -1069,6 +1075,7 @@ private:
|
|
1069
1075
|
}
|
1070
1076
|
|
1071
1077
|
size_t onAppInputData(const ClientPtr &client, const StaticString &data) {
|
1078
|
+
RH_LOG_EVENT(client, "onAppInputData");
|
1072
1079
|
if (!client->connected()) {
|
1073
1080
|
return 0;
|
1074
1081
|
}
|
@@ -1110,10 +1117,12 @@ private:
|
|
1110
1117
|
}
|
1111
1118
|
|
1112
1119
|
void onAppInputChunk(const ClientPtr &client, const StaticString &data) {
|
1120
|
+
RH_LOG_EVENT(client, "onAppInputChunk");
|
1113
1121
|
writeToClientOutputPipe(client, data);
|
1114
1122
|
}
|
1115
1123
|
|
1116
1124
|
void onAppInputEof(const ClientPtr &client) {
|
1125
|
+
RH_LOG_EVENT(client, "onAppInputEof");
|
1117
1126
|
if (!client->connected()) {
|
1118
1127
|
return;
|
1119
1128
|
}
|
@@ -1124,6 +1133,7 @@ private:
|
|
1124
1133
|
}
|
1125
1134
|
|
1126
1135
|
void onAppInputError(const ClientPtr &client, const char *message, int errorCode) {
|
1136
|
+
RH_LOG_EVENT(client, "onAppInputError");
|
1127
1137
|
if (!client->connected()) {
|
1128
1138
|
return;
|
1129
1139
|
}
|
@@ -1143,6 +1153,7 @@ private:
|
|
1143
1153
|
}
|
1144
1154
|
|
1145
1155
|
void onClientOutputPipeCommit(const ClientPtr &client) {
|
1156
|
+
RH_LOG_EVENT(client, "onClientOutputPipeCommit");
|
1146
1157
|
if (!client->connected()) {
|
1147
1158
|
return;
|
1148
1159
|
}
|
@@ -1166,6 +1177,7 @@ private:
|
|
1166
1177
|
void onClientOutputPipeData(const ClientPtr &client, const char *data,
|
1167
1178
|
size_t size, const FileBackedPipe::ConsumeCallback &consumed)
|
1168
1179
|
{
|
1180
|
+
RH_LOG_EVENT(client, "onClientOutputPipeData");
|
1169
1181
|
if (!client->connected()) {
|
1170
1182
|
return;
|
1171
1183
|
}
|
@@ -1196,6 +1208,7 @@ private:
|
|
1196
1208
|
}
|
1197
1209
|
|
1198
1210
|
void onClientOutputPipeEnd(const ClientPtr &client) {
|
1211
|
+
RH_LOG_EVENT(client, "onClientOutputPipeEnd");
|
1199
1212
|
if (!client->connected()) {
|
1200
1213
|
return;
|
1201
1214
|
}
|
@@ -1206,6 +1219,7 @@ private:
|
|
1206
1219
|
}
|
1207
1220
|
|
1208
1221
|
void onClientOutputPipeError(const ClientPtr &client, int errorCode) {
|
1222
|
+
RH_LOG_EVENT(client, "onClientOutputPipeError");
|
1209
1223
|
if (!client->connected()) {
|
1210
1224
|
return;
|
1211
1225
|
}
|
@@ -1218,6 +1232,7 @@ private:
|
|
1218
1232
|
}
|
1219
1233
|
|
1220
1234
|
void onClientOutputWritable(const ClientPtr &client) {
|
1235
|
+
RH_LOG_EVENT(client, "onClientOutputWritable");
|
1221
1236
|
if (!client->connected()) {
|
1222
1237
|
return;
|
1223
1238
|
}
|
@@ -1323,7 +1338,7 @@ private:
|
|
1323
1338
|
|
1324
1339
|
|
1325
1340
|
size_t onClientInputData(const ClientPtr &client, const StaticString &data) {
|
1326
|
-
|
1341
|
+
RH_LOG_EVENT(client, "onClientInputData");
|
1327
1342
|
if (!client->connected()) {
|
1328
1343
|
return 0;
|
1329
1344
|
}
|
@@ -1374,7 +1389,7 @@ private:
|
|
1374
1389
|
}
|
1375
1390
|
|
1376
1391
|
void onClientEof(const ClientPtr &client) {
|
1377
|
-
|
1392
|
+
RH_LOG_EVENT(client, "onClientEof; client sent EOF");
|
1378
1393
|
switch (client->state) {
|
1379
1394
|
case Client::BUFFERING_REQUEST_BODY:
|
1380
1395
|
state_bufferingRequestBody_onClientEof(client);
|
@@ -1389,7 +1404,7 @@ private:
|
|
1389
1404
|
}
|
1390
1405
|
|
1391
1406
|
void onClientInputError(const ClientPtr &client, const char *message, int errnoCode) {
|
1392
|
-
|
1407
|
+
RH_LOG_EVENT(client, "onClientInputError");
|
1393
1408
|
if (!client->connected()) {
|
1394
1409
|
return;
|
1395
1410
|
}
|
@@ -1410,7 +1425,7 @@ private:
|
|
1410
1425
|
|
1411
1426
|
|
1412
1427
|
void onClientBodyBufferData(const ClientPtr &client, const char *data, size_t size, const FileBackedPipe::ConsumeCallback &consumed) {
|
1413
|
-
|
1428
|
+
RH_LOG_EVENT(client, "onClientBodyBufferData");
|
1414
1429
|
if (!client->connected()) {
|
1415
1430
|
return;
|
1416
1431
|
}
|
@@ -1425,7 +1440,7 @@ private:
|
|
1425
1440
|
}
|
1426
1441
|
|
1427
1442
|
void onClientBodyBufferError(const ClientPtr &client, int errorCode) {
|
1428
|
-
|
1443
|
+
RH_LOG_EVENT(client, "onClientBodyBufferError");
|
1429
1444
|
if (!client->connected()) {
|
1430
1445
|
return;
|
1431
1446
|
}
|
@@ -1438,7 +1453,7 @@ private:
|
|
1438
1453
|
}
|
1439
1454
|
|
1440
1455
|
void onClientBodyBufferEnd(const ClientPtr &client) {
|
1441
|
-
|
1456
|
+
RH_LOG_EVENT(client, "onClientBodyBufferEnd");
|
1442
1457
|
if (!client->connected()) {
|
1443
1458
|
return;
|
1444
1459
|
}
|
@@ -1453,7 +1468,7 @@ private:
|
|
1453
1468
|
}
|
1454
1469
|
|
1455
1470
|
void onClientBodyBufferCommit(const ClientPtr &client) {
|
1456
|
-
|
1471
|
+
RH_LOG_EVENT(client, "onClientBodyBufferCommit");
|
1457
1472
|
if (!client->connected()) {
|
1458
1473
|
return;
|
1459
1474
|
}
|
@@ -1468,7 +1483,7 @@ private:
|
|
1468
1483
|
}
|
1469
1484
|
|
1470
1485
|
void onAppOutputWritable(const ClientPtr &client) {
|
1471
|
-
|
1486
|
+
RH_LOG_EVENT(client, "onAppOutputWritable");
|
1472
1487
|
if (!client->connected()) {
|
1473
1488
|
return;
|
1474
1489
|
}
|
@@ -1487,7 +1502,7 @@ private:
|
|
1487
1502
|
|
1488
1503
|
|
1489
1504
|
void onTimeout(const ClientPtr &client) {
|
1490
|
-
|
1505
|
+
RH_LOG_EVENT(client, "onTimeout");
|
1491
1506
|
if (!client->connected()) {
|
1492
1507
|
return;
|
1493
1508
|
}
|
@@ -389,6 +389,22 @@ private:
|
|
389
389
|
type = UNINITIALIZED;
|
390
390
|
dataReader.setMaxSize(1024 * 128);
|
391
391
|
}
|
392
|
+
|
393
|
+
template<typename Stream>
|
394
|
+
void inspect(Stream &stream) const {
|
395
|
+
stream << " * Client " << (int) fd << "\n";
|
396
|
+
stream << " Initialized : " << bool(type == LOGGER) << "\n";
|
397
|
+
stream << " Node name : " << nodeName << "\n";
|
398
|
+
stream << " Open transactions: (" << openTransactions.size() << ")";
|
399
|
+
set<string>::const_iterator it, end = openTransactions.end();
|
400
|
+
for (it = openTransactions.begin(); it != end; it++) {
|
401
|
+
stream << " " << *it;
|
402
|
+
}
|
403
|
+
stream << "\n";
|
404
|
+
stream << " Connection state : " << getStateName() << "\n";
|
405
|
+
stream << " Message state : " << messageServer.getStateName() << "\n";
|
406
|
+
stream << " Outbox : " << outbox.size() << " bytes\n";
|
407
|
+
}
|
392
408
|
};
|
393
409
|
|
394
410
|
typedef shared_ptr<Client> ClientPtr;
|
@@ -639,15 +655,6 @@ private:
|
|
639
655
|
char writeCountStr[sizeof(unsigned int) * 2 + 1];
|
640
656
|
integerToHexatri(transaction->writeCount, writeCountStr);
|
641
657
|
transaction->writeCount++;
|
642
|
-
transaction->data.reserve(transaction->data.size() +
|
643
|
-
transaction->txnId.size() +
|
644
|
-
1 +
|
645
|
-
timestamp.size() +
|
646
|
-
1 +
|
647
|
-
strlen(writeCountStr) +
|
648
|
-
1 +
|
649
|
-
data.size() +
|
650
|
-
1);
|
651
658
|
transaction->data.append(transaction->txnId);
|
652
659
|
transaction->data.append(" ");
|
653
660
|
transaction->data.append(timestamp);
|
@@ -863,7 +870,7 @@ protected:
|
|
863
870
|
}
|
864
871
|
|
865
872
|
transaction = make_shared<Transaction>(this, ev_now(getLoop()));
|
866
|
-
if (unionStationKey.empty()) {
|
873
|
+
if (unionStationKey.empty() || unionStationKey == "-") {
|
867
874
|
char tempNodeId[MD5_HEX_SIZE];
|
868
875
|
|
869
876
|
if (nodeId == NULL) {
|
@@ -1156,7 +1163,13 @@ public:
|
|
1156
1163
|
TransactionMap::const_iterator it;
|
1157
1164
|
TransactionMap::const_iterator end = transactions.end();
|
1158
1165
|
|
1159
|
-
|
1166
|
+
ClientSet::const_iterator cit, cend = getClients().end();
|
1167
|
+
stream << "Clients:\n";
|
1168
|
+
stream << " Count: " << getClients().size() << "\n";
|
1169
|
+
for (cit = getClients().begin(); cit != cend; cit++) {
|
1170
|
+
const Client *client = static_cast<Client *>(*cit);
|
1171
|
+
client->inspect(stream);
|
1172
|
+
}
|
1160
1173
|
stream << "\n";
|
1161
1174
|
|
1162
1175
|
stream << "RemoteSender:\n";
|
data/ext/oxt/backtrace.hpp
CHANGED
@@ -39,12 +39,10 @@
|
|
39
39
|
*
|
40
40
|
* <h2>Initialization</h2>
|
41
41
|
* Every thread that is to contain backtrace information <b>must</b> be
|
42
|
-
* initialized.
|
43
|
-
*
|
44
|
-
*
|
45
|
-
*
|
46
|
-
* If you use oxt::thread, then initialization will be automatically done for
|
47
|
-
* you for that partciular thread.
|
42
|
+
* initialized. This is done by creating a `thread_local_context` object,
|
43
|
+
* and calling `set_thread_local_context()` with that object.
|
44
|
+
* `oxt::initialize()` automatically does this for the calling thread,
|
45
|
+
* and `oxt::thread` does this automatically as well.
|
48
46
|
*
|
49
47
|
* <h2>Basic usage</h2>
|
50
48
|
* Backtrace points must be specified manually in the code using TRACE_POINT().
|
@@ -33,6 +33,7 @@ namespace oxt {
|
|
33
33
|
|
34
34
|
#define TRACE_POINT() do { /* nothing */ } while (false)
|
35
35
|
#define TRACE_POINT_WITH_NAME(name) do { /* nothing */ } while (false)
|
36
|
+
#define TRACE_POINT_WITH_DATA(data) do { /* nothing */ } while (false)
|
36
37
|
#define UPDATE_TRACE_POINT() do { /* nothing */ } while (false)
|
37
38
|
|
38
39
|
} // namespace oxt
|
@@ -41,19 +41,25 @@ namespace oxt {
|
|
41
41
|
* Except if you set the 'detached' argument to true.
|
42
42
|
*/
|
43
43
|
struct trace_point {
|
44
|
+
struct detached { };
|
45
|
+
|
44
46
|
const char *function;
|
45
47
|
const char *source;
|
46
|
-
|
48
|
+
const char *data;
|
49
|
+
unsigned short line;
|
47
50
|
bool m_detached;
|
48
51
|
|
49
|
-
trace_point(const char *function, const char *source, unsigned
|
50
|
-
|
52
|
+
trace_point(const char *function, const char *source, unsigned short line,
|
53
|
+
const char *data = 0);
|
54
|
+
trace_point(const char *function, const char *source, unsigned short line,
|
55
|
+
const char *data, const detached &detached_tag);
|
51
56
|
~trace_point();
|
52
|
-
void update(const char *source, unsigned
|
57
|
+
void update(const char *source, unsigned short line);
|
53
58
|
};
|
54
59
|
|
55
60
|
#define TRACE_POINT() oxt::trace_point __p(BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)
|
56
61
|
#define TRACE_POINT_WITH_NAME(name) oxt::trace_point __p(name, __FILE__, __LINE__)
|
62
|
+
#define TRACE_POINT_WITH_DATA(data) oxt::trace_point __p(BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, data)
|
57
63
|
#define UPDATE_TRACE_POINT() __p.update(__FILE__, __LINE__)
|
58
64
|
|
59
65
|
} // namespace oxt
|