passenger 3.0.8 → 3.0.9
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/NEWS +9 -0
- data/bin/passenger-install-nginx-module +1 -1
- data/build/basics.rb +0 -1
- data/build/cxx_tests.rb +5 -0
- data/build/rpm.rb +1 -1
- data/doc/Users guide Apache.html +1 -1
- data/doc/Users guide Nginx.html +1 -1
- data/ext/apache2/Configuration.cpp +12 -0
- data/ext/apache2/Configuration.hpp +12 -1
- data/ext/apache2/Hooks.cpp +2 -0
- data/ext/common/AgentsStarter.cpp +4 -0
- data/ext/common/AgentsStarter.h +2 -0
- data/ext/common/AgentsStarter.hpp +4 -0
- data/ext/common/Constants.h +1 -1
- data/ext/common/Logging.h +481 -261
- data/ext/common/LoggingAgent/LoggingServer.h +10 -4
- data/ext/common/LoggingAgent/Main.cpp +7 -2
- data/ext/common/LoggingAgent/RemoteSender.h +25 -3
- data/ext/common/MessageChannel.h +18 -227
- data/ext/common/MessageClient.h +95 -92
- data/ext/common/Utils/IOUtils.cpp +114 -1
- data/ext/common/Utils/IOUtils.h +57 -1
- data/ext/common/Utils/MessageIO.h +576 -0
- data/ext/nginx/Configuration.c +35 -0
- data/ext/nginx/Configuration.h +2 -0
- data/ext/nginx/ContentHandler.c +17 -6
- data/ext/nginx/ngx_http_passenger_module.c +8 -0
- data/lib/phusion_passenger.rb +2 -2
- data/lib/phusion_passenger/analytics_logger.rb +174 -117
- data/lib/phusion_passenger/app_process.rb +14 -2
- data/test/cxx/CxxTestMain.cpp +14 -19
- data/test/cxx/IOUtilsTest.cpp +68 -18
- data/test/cxx/LoggingTest.cpp +20 -24
- data/test/cxx/MessageChannelTest.cpp +1 -1
- data/test/cxx/MessageIOTest.cpp +310 -0
- data/test/cxx/TestSupport.cpp +47 -0
- data/test/cxx/TestSupport.h +8 -0
- data/test/ruby/analytics_logger_spec.rb +20 -28
- data/test/tut/tut.h +2 -0
- metadata +11 -11
- data/build/rdoctask.rb +0 -209
- data/test/cxx/HttpStatusExtractorTest.cpp +0 -198
@@ -185,7 +185,8 @@ private:
|
|
185
185
|
virtual void dump(ostream &stream) const {
|
186
186
|
stream << " Log file: file=" << filename << ", "
|
187
187
|
"opened=" << opened << ", "
|
188
|
-
"
|
188
|
+
"lastUsed=" << long(ev_now(server->getLoop()) - lastUsed) << "s ago, "
|
189
|
+
"lastFlushed=" << long(ev_now(server->getLoop()) - lastFlushed) << "s ago\n";
|
189
190
|
}
|
190
191
|
};
|
191
192
|
|
@@ -268,7 +269,8 @@ private:
|
|
268
269
|
"node=" << nodeName << ", "
|
269
270
|
"category=" << category << ", "
|
270
271
|
"opened=" << opened << ", "
|
271
|
-
"
|
272
|
+
"lastUsed=" << long(ev_now(server->getLoop()) - lastUsed) << "s ago, "
|
273
|
+
"lastFlushed=" << long(ev_now(server->getLoop()) - lastFlushed) << "s ago, "
|
272
274
|
"bufferSize=" << bufferSize <<
|
273
275
|
"\n";
|
274
276
|
}
|
@@ -1206,11 +1208,15 @@ public:
|
|
1206
1208
|
gid_t gid = GROUP_NOT_GIVEN,
|
1207
1209
|
const string &unionStationGatewayAddress = DEFAULT_UNION_STATION_GATEWAY_ADDRESS,
|
1208
1210
|
unsigned short unionStationGatewayPort = DEFAULT_UNION_STATION_GATEWAY_PORT,
|
1209
|
-
const string &unionStationGatewayCert = ""
|
1211
|
+
const string &unionStationGatewayCert = "",
|
1212
|
+
const string &unionStationProxyAddress = "",
|
1213
|
+
const string &unionStationProxyPort = "")
|
1210
1214
|
: EventedMessageServer(loop, fd, accountsDatabase),
|
1211
1215
|
remoteSender(unionStationGatewayAddress,
|
1212
1216
|
unionStationGatewayPort,
|
1213
|
-
unionStationGatewayCert
|
1217
|
+
unionStationGatewayCert,
|
1218
|
+
unionStationProxyAddress,
|
1219
|
+
unionStationProxyPort),
|
1214
1220
|
garbageCollectionTimer(loop),
|
1215
1221
|
sinkFlushingTimer(loop),
|
1216
1222
|
exitTimer(loop)
|
@@ -162,7 +162,9 @@ main(int argc, char *argv[]) {
|
|
162
162
|
false, DEFAULT_UNION_STATION_GATEWAY_ADDRESS);
|
163
163
|
int unionStationGatewayPort = options.getInt("union_station_gateway_port",
|
164
164
|
false, DEFAULT_UNION_STATION_GATEWAY_PORT);
|
165
|
-
string unionStationGatewayCert
|
165
|
+
string unionStationGatewayCert = options.get("union_station_gateway_cert", false);
|
166
|
+
string unionStationProxyAddress = options.get("union_station_proxy_address", false);
|
167
|
+
string unionStationProxyType = options.get("union_station_proxy_type", false);
|
166
168
|
|
167
169
|
curl_global_init(CURL_GLOBAL_ALL);
|
168
170
|
|
@@ -251,7 +253,9 @@ main(int argc, char *argv[]) {
|
|
251
253
|
"u=rwx,g=rx,o=rx", GROUP_NOT_GIVEN,
|
252
254
|
unionStationGatewayAddress,
|
253
255
|
unionStationGatewayPort,
|
254
|
-
unionStationGatewayCert
|
256
|
+
unionStationGatewayCert,
|
257
|
+
unionStationProxyAddress,
|
258
|
+
unionStationProxyType);
|
255
259
|
loggingServer = &server;
|
256
260
|
|
257
261
|
|
@@ -276,6 +280,7 @@ main(int argc, char *argv[]) {
|
|
276
280
|
|
277
281
|
/********** Initialized! Enter main loop... **********/
|
278
282
|
|
283
|
+
P_DEBUG("Logging agent online, listening at " << socketAddress);
|
279
284
|
ev_loop(eventLoop, 0);
|
280
285
|
return exitCode;
|
281
286
|
} catch (const tracable_exception &e) {
|
@@ -72,6 +72,8 @@ private:
|
|
72
72
|
string ip;
|
73
73
|
unsigned short port;
|
74
74
|
string certificate;
|
75
|
+
string proxyAddress;
|
76
|
+
string proxyType;
|
75
77
|
|
76
78
|
CURL *curl;
|
77
79
|
struct curl_slist *headers;
|
@@ -103,6 +105,16 @@ private:
|
|
103
105
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
104
106
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlDataReceived);
|
105
107
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
|
108
|
+
if (!proxyAddress.empty()) {
|
109
|
+
curl_easy_setopt(curl, CURLOPT_PROXY, proxyAddress.c_str());
|
110
|
+
if (proxyType.empty() || proxyType == "http") {
|
111
|
+
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
|
112
|
+
} else if (proxyType == "socks5") {
|
113
|
+
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
|
114
|
+
} else {
|
115
|
+
throw RuntimeException("Only 'http' and 'socks5' proxies are supported.");
|
116
|
+
}
|
117
|
+
}
|
106
118
|
if (certificate.empty()) {
|
107
119
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
108
120
|
} else {
|
@@ -129,10 +141,14 @@ private:
|
|
129
141
|
}
|
130
142
|
|
131
143
|
public:
|
132
|
-
Server(const string &ip, const string &hostName, unsigned short port, const string &cert
|
144
|
+
Server(const string &ip, const string &hostName, unsigned short port, const string &cert,
|
145
|
+
const string &proxyAddress, const string &proxyType)
|
146
|
+
{
|
133
147
|
this->ip = ip;
|
134
148
|
this->port = port;
|
135
149
|
certificate = cert;
|
150
|
+
this->proxyAddress = proxyAddress;
|
151
|
+
this->proxyType = proxyType;
|
136
152
|
|
137
153
|
hostHeader = "Host: " + hostName;
|
138
154
|
headers = NULL;
|
@@ -245,6 +261,8 @@ private:
|
|
245
261
|
string gatewayAddress;
|
246
262
|
unsigned short gatewayPort;
|
247
263
|
string certificate;
|
264
|
+
string proxyAddress;
|
265
|
+
string proxyType;
|
248
266
|
BlockingQueue<Item> queue;
|
249
267
|
oxt::thread *thr;
|
250
268
|
|
@@ -298,7 +316,8 @@ private:
|
|
298
316
|
|
299
317
|
servers.clear();
|
300
318
|
for (it = ips.begin(); it != ips.end(); it++) {
|
301
|
-
ServerPtr server
|
319
|
+
ServerPtr server = make_shared<Server>(*it, gatewayAddress, gatewayPort,
|
320
|
+
certificate, proxyAddress, proxyType);
|
302
321
|
if (server->ping()) {
|
303
322
|
servers.push_back(server);
|
304
323
|
} else {
|
@@ -418,12 +437,15 @@ private:
|
|
418
437
|
}
|
419
438
|
|
420
439
|
public:
|
421
|
-
RemoteSender(const string &gatewayAddress, unsigned short gatewayPort, const string &certificate
|
440
|
+
RemoteSender(const string &gatewayAddress, unsigned short gatewayPort, const string &certificate,
|
441
|
+
const string &proxyAddress, const string &proxyType)
|
422
442
|
: queue(1024)
|
423
443
|
{
|
424
444
|
this->gatewayAddress = gatewayAddress;
|
425
445
|
this->gatewayPort = gatewayPort;
|
426
446
|
this->certificate = certificate;
|
447
|
+
this->proxyAddress = proxyAddress;
|
448
|
+
this->proxyType = proxyType;
|
427
449
|
thr = new oxt::thread(
|
428
450
|
boost::bind(&RemoteSender::threadMain, this),
|
429
451
|
"RemoteSender thread",
|
data/ext/common/MessageChannel.h
CHANGED
@@ -53,6 +53,7 @@
|
|
53
53
|
#include "Utils/Timer.h"
|
54
54
|
#include "Utils/MemZeroGuard.h"
|
55
55
|
#include "Utils/IOUtils.h"
|
56
|
+
#include "Utils/MessageIO.h"
|
56
57
|
|
57
58
|
namespace Passenger {
|
58
59
|
|
@@ -194,52 +195,9 @@ public:
|
|
194
195
|
* @pre None of the message elements may contain a NUL character (<tt>'\\0'</tt>).
|
195
196
|
* @see read(), write(const char *, ...)
|
196
197
|
*/
|
197
|
-
template<typename StringArrayType
|
198
|
+
template<typename StringArrayType>
|
198
199
|
void write(const StringArrayType &args) {
|
199
|
-
|
200
|
-
string data;
|
201
|
-
uint16_t dataSize = 0;
|
202
|
-
|
203
|
-
for (it = args.begin(); it != args.end(); it++) {
|
204
|
-
dataSize += it->size() + 1;
|
205
|
-
}
|
206
|
-
data.reserve(dataSize + sizeof(dataSize));
|
207
|
-
dataSize = htons(dataSize);
|
208
|
-
data.append((const char *) &dataSize, sizeof(dataSize));
|
209
|
-
for (it = args.begin(); it != args.end(); it++) {
|
210
|
-
data.append(*it);
|
211
|
-
data.append(1, DELIMITER);
|
212
|
-
}
|
213
|
-
|
214
|
-
writeExact(fd, data);
|
215
|
-
}
|
216
|
-
|
217
|
-
/**
|
218
|
-
* Send an array message, which consists of the given elements, over the underlying
|
219
|
-
* file descriptor.
|
220
|
-
*
|
221
|
-
* @param args The message elements.
|
222
|
-
* @throws SystemException An error occured while writing the data to the file descriptor.
|
223
|
-
* @throws boost::thread_interrupted
|
224
|
-
* @pre None of the message elements may contain a NUL character (<tt>'\\0'</tt>).
|
225
|
-
* @see read(), write(const char *, ...)
|
226
|
-
*/
|
227
|
-
void write(const list<string> &args) {
|
228
|
-
write<list<string>, list<string>::const_iterator>(args);
|
229
|
-
}
|
230
|
-
|
231
|
-
/**
|
232
|
-
* Send an array message, which consists of the given elements, over the underlying
|
233
|
-
* file descriptor.
|
234
|
-
*
|
235
|
-
* @param args The message elements.
|
236
|
-
* @throws SystemException An error occured while writing the data to the file descriptor.
|
237
|
-
* @throws boost::thread_interrupted
|
238
|
-
* @pre None of the message elements may contain a NUL character (<tt>'\\0'</tt>).
|
239
|
-
* @see read(), write(const char *, ...)
|
240
|
-
*/
|
241
|
-
void write(const vector<string> &args) {
|
242
|
-
write<vector<string>, vector<string>::const_iterator>(args);
|
200
|
+
writeArrayMessage(fd, args);
|
243
201
|
}
|
244
202
|
|
245
203
|
/**
|
@@ -252,18 +210,7 @@ public:
|
|
252
210
|
* @pre None of the message elements may contain a NUL character (<tt>'\\0'</tt>).
|
253
211
|
*/
|
254
212
|
void write(const char *name, va_list &ap) {
|
255
|
-
|
256
|
-
args.push_back(name);
|
257
|
-
|
258
|
-
while (true) {
|
259
|
-
const char *arg = va_arg(ap, const char *);
|
260
|
-
if (arg == NULL) {
|
261
|
-
break;
|
262
|
-
} else {
|
263
|
-
args.push_back(arg);
|
264
|
-
}
|
265
|
-
}
|
266
|
-
write(args);
|
213
|
+
writeArrayMessage(fd, name, ap);
|
267
214
|
}
|
268
215
|
|
269
216
|
/**
|
@@ -297,8 +244,7 @@ public:
|
|
297
244
|
* @throws boost::thread_interrupted
|
298
245
|
*/
|
299
246
|
void writeUint32(unsigned int value) {
|
300
|
-
|
301
|
-
writeExact(fd, &l, sizeof(uint32_t));
|
247
|
+
Passenger::writeUint32(fd, value);
|
302
248
|
}
|
303
249
|
|
304
250
|
/**
|
@@ -314,7 +260,7 @@ public:
|
|
314
260
|
* @see readScalar(), writeScalar(const char *, unsigned int)
|
315
261
|
*/
|
316
262
|
void writeScalar(const string &str) {
|
317
|
-
|
263
|
+
writeScalarMessage(fd, str);
|
318
264
|
}
|
319
265
|
|
320
266
|
/**
|
@@ -332,8 +278,7 @@ public:
|
|
332
278
|
* @see readScalar(), writeScalar(const string &)
|
333
279
|
*/
|
334
280
|
void writeScalar(const char *data, unsigned int size) {
|
335
|
-
|
336
|
-
writeExact(fd, data, size);
|
281
|
+
writeScalarMessage(fd, data, size);
|
337
282
|
}
|
338
283
|
|
339
284
|
/**
|
@@ -348,69 +293,10 @@ public:
|
|
348
293
|
* @see readFileDescriptor()
|
349
294
|
*/
|
350
295
|
void writeFileDescriptor(int fileDescriptor, bool negotiate = true) {
|
351
|
-
// See message_channel.rb for more info about negotiation.
|
352
|
-
if (negotiate) {
|
353
|
-
vector<string> args;
|
354
|
-
|
355
|
-
if (!read(args)) {
|
356
|
-
throw IOException("Unexpected end of stream encountered while pre-negotiating a file descriptor");
|
357
|
-
} else if (args.size() != 1 || args[0] != "pass IO") {
|
358
|
-
throw IOException("FD passing pre-negotiation message expected.");
|
359
|
-
}
|
360
|
-
}
|
361
|
-
|
362
|
-
struct msghdr msg;
|
363
|
-
struct iovec vec;
|
364
|
-
char dummy[1];
|
365
|
-
#if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)
|
366
|
-
struct {
|
367
|
-
struct cmsghdr header;
|
368
|
-
int fd;
|
369
|
-
} control_data;
|
370
|
-
#else
|
371
|
-
char control_data[CMSG_SPACE(sizeof(int))];
|
372
|
-
#endif
|
373
|
-
struct cmsghdr *control_header;
|
374
|
-
int ret;
|
375
|
-
|
376
|
-
msg.msg_name = NULL;
|
377
|
-
msg.msg_namelen = 0;
|
378
|
-
|
379
|
-
/* Linux and Solaris require msg_iov to be non-NULL. */
|
380
|
-
dummy[0] = '\0';
|
381
|
-
vec.iov_base = dummy;
|
382
|
-
vec.iov_len = sizeof(dummy);
|
383
|
-
msg.msg_iov = &vec;
|
384
|
-
msg.msg_iovlen = 1;
|
385
|
-
|
386
|
-
msg.msg_control = (caddr_t) &control_data;
|
387
|
-
msg.msg_controllen = sizeof(control_data);
|
388
|
-
msg.msg_flags = 0;
|
389
|
-
|
390
|
-
control_header = CMSG_FIRSTHDR(&msg);
|
391
|
-
control_header->cmsg_level = SOL_SOCKET;
|
392
|
-
control_header->cmsg_type = SCM_RIGHTS;
|
393
|
-
#if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)
|
394
|
-
control_header->cmsg_len = sizeof(control_data);
|
395
|
-
control_data.fd = fileDescriptor;
|
396
|
-
#else
|
397
|
-
control_header->cmsg_len = CMSG_LEN(sizeof(int));
|
398
|
-
memcpy(CMSG_DATA(control_header), &fileDescriptor, sizeof(int));
|
399
|
-
#endif
|
400
|
-
|
401
|
-
ret = syscalls::sendmsg(fd, &msg, 0);
|
402
|
-
if (ret == -1) {
|
403
|
-
throw SystemException("Cannot send file descriptor with sendmsg()", errno);
|
404
|
-
}
|
405
|
-
|
406
296
|
if (negotiate) {
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
throw IOException("Unexpected end of stream encountered while post-negotiating a file descriptor");
|
411
|
-
} else if (args.size() != 1 || args[0] != "got IO") {
|
412
|
-
throw IOException("FD passing post-negotiation message expected.");
|
413
|
-
}
|
297
|
+
Passenger::writeFileDescriptorWithNegotiation(fd, fileDescriptor);
|
298
|
+
} else {
|
299
|
+
Passenger::writeFileDescriptor(fd, fileDescriptor);
|
414
300
|
}
|
415
301
|
}
|
416
302
|
|
@@ -425,44 +311,12 @@ public:
|
|
425
311
|
* @see write()
|
426
312
|
*/
|
427
313
|
bool read(vector<string> &args) {
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
ret = syscalls::read(fd, (char *) &size + alreadyRead, sizeof(size) - alreadyRead);
|
434
|
-
if (ret == -1) {
|
435
|
-
throw SystemException("read() failed", errno);
|
436
|
-
} else if (ret == 0) {
|
437
|
-
return false;
|
438
|
-
}
|
439
|
-
alreadyRead += ret;
|
440
|
-
} while (alreadyRead < sizeof(size));
|
441
|
-
size = ntohs(size);
|
442
|
-
|
443
|
-
string buffer;
|
444
|
-
args.clear();
|
445
|
-
buffer.reserve(size);
|
446
|
-
while (buffer.size() < size) {
|
447
|
-
char tmp[1024 * 8];
|
448
|
-
ret = syscalls::read(fd, tmp, min(size - buffer.size(), sizeof(tmp)));
|
449
|
-
if (ret == -1) {
|
450
|
-
throw SystemException("read() failed", errno);
|
451
|
-
} else if (ret == 0) {
|
452
|
-
return false;
|
453
|
-
}
|
454
|
-
buffer.append(tmp, ret);
|
455
|
-
}
|
456
|
-
|
457
|
-
if (!buffer.empty()) {
|
458
|
-
string::size_type start = 0, pos;
|
459
|
-
const string &const_buffer(buffer);
|
460
|
-
while ((pos = const_buffer.find('\0', start)) != string::npos) {
|
461
|
-
args.push_back(const_buffer.substr(start, pos - start));
|
462
|
-
start = pos + 1;
|
463
|
-
}
|
314
|
+
try {
|
315
|
+
args = readArrayMessage(fd);
|
316
|
+
return true;
|
317
|
+
} catch (const EOFException &) {
|
318
|
+
return false;
|
464
319
|
}
|
465
|
-
return true;
|
466
320
|
}
|
467
321
|
|
468
322
|
/**
|
@@ -610,74 +464,11 @@ public:
|
|
610
464
|
* @throws boost::thread_interrupted
|
611
465
|
*/
|
612
466
|
int readFileDescriptor(bool negotiate = true) {
|
613
|
-
// See message_channel.rb for more info about negotiation.
|
614
|
-
if (negotiate) {
|
615
|
-
write("pass IO", NULL);
|
616
|
-
}
|
617
|
-
|
618
|
-
struct msghdr msg;
|
619
|
-
struct iovec vec;
|
620
|
-
char dummy[1];
|
621
|
-
#if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)
|
622
|
-
// File descriptor passing macros (CMSG_*) seem to be broken
|
623
|
-
// on 64-bit MacOS X. This structure works around the problem.
|
624
|
-
struct {
|
625
|
-
struct cmsghdr header;
|
626
|
-
int fd;
|
627
|
-
} control_data;
|
628
|
-
#define EXPECTED_CMSG_LEN sizeof(control_data)
|
629
|
-
#else
|
630
|
-
char control_data[CMSG_SPACE(sizeof(int))];
|
631
|
-
#define EXPECTED_CMSG_LEN CMSG_LEN(sizeof(int))
|
632
|
-
#endif
|
633
|
-
struct cmsghdr *control_header;
|
634
|
-
int ret;
|
635
|
-
|
636
|
-
msg.msg_name = NULL;
|
637
|
-
msg.msg_namelen = 0;
|
638
|
-
|
639
|
-
dummy[0] = '\0';
|
640
|
-
vec.iov_base = dummy;
|
641
|
-
vec.iov_len = sizeof(dummy);
|
642
|
-
msg.msg_iov = &vec;
|
643
|
-
msg.msg_iovlen = 1;
|
644
|
-
|
645
|
-
msg.msg_control = (caddr_t) &control_data;
|
646
|
-
msg.msg_controllen = sizeof(control_data);
|
647
|
-
msg.msg_flags = 0;
|
648
|
-
|
649
|
-
ret = syscalls::recvmsg(fd, &msg, 0);
|
650
|
-
if (ret == -1) {
|
651
|
-
throw SystemException("Cannot read file descriptor with recvmsg()", errno);
|
652
|
-
}
|
653
|
-
|
654
|
-
control_header = CMSG_FIRSTHDR(&msg);
|
655
|
-
if (control_header == NULL) {
|
656
|
-
throw IOException("No valid file descriptor received.");
|
657
|
-
}
|
658
|
-
if (control_header->cmsg_len != EXPECTED_CMSG_LEN
|
659
|
-
|| control_header->cmsg_level != SOL_SOCKET
|
660
|
-
|| control_header->cmsg_type != SCM_RIGHTS) {
|
661
|
-
throw IOException("No valid file descriptor received.");
|
662
|
-
}
|
663
|
-
|
664
|
-
#if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)
|
665
|
-
int fd = control_data.fd;
|
666
|
-
#else
|
667
|
-
int fd = *((int *) CMSG_DATA(control_header));
|
668
|
-
#endif
|
669
|
-
|
670
467
|
if (negotiate) {
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
this_thread::disable_syscall_interruption dsi;
|
675
|
-
syscalls::close(fd);
|
676
|
-
throw;
|
677
|
-
}
|
468
|
+
Passenger::readFileDescriptorWithNegotiation(fd);
|
469
|
+
} else {
|
470
|
+
Passenger::readFileDescriptor(fd);
|
678
471
|
}
|
679
|
-
|
680
|
-
return fd;
|
681
472
|
}
|
682
473
|
|
683
474
|
/**
|