passenger 6.0.27 → 6.1.0
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 +11 -1
- data/CONTRIBUTORS +2 -0
- data/bin/passenger-install-apache2-module +6 -3
- data/bin/passenger-install-nginx-module +8 -3
- data/build/support/cxx_dependency_map.rb +3 -621
- data/dev/index_cxx_dependencies.rb +4 -0
- data/package.json +1 -1
- data/src/agent/Core/ApplicationPool/Implementation.cpp +1 -1
- data/src/agent/Core/ApplicationPool/Socket.h +3 -3
- data/src/agent/Core/ApplicationPool/TestSession.h +3 -4
- data/src/agent/Core/Config.h +1 -6
- data/src/agent/Core/Controller/Config.h +1 -1
- data/src/agent/Core/CoreMain.cpp +1 -0
- data/src/agent/Core/SecurityUpdateChecker.h +10 -1
- data/src/agent/Core/SpawningKit/Exceptions.h +0 -1
- data/src/agent/Core/SpawningKit/Handshake/Perform.h +13 -2
- data/src/agent/Shared/Fundamentals/AbortHandler.cpp +23 -5
- data/src/agent/Shared/Fundamentals/AbortHandler.h +10 -22
- data/src/agent/Shared/Fundamentals/Initialization.cpp +1 -0
- data/src/agent/Watchdog/Config.h +1 -1
- data/src/apache2_module/ConfigGeneral/AutoGeneratedDefinitions.cpp +5 -0
- data/src/apache2_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.cpp +5 -0
- data/src/apache2_module/ConfigGeneral/AutoGeneratedSetterFuncs.cpp +14 -0
- data/src/apache2_module/DirConfig/AutoGeneratedCreateFunction.cpp +3 -0
- data/src/apache2_module/DirConfig/AutoGeneratedHeaderSerialization.cpp +3 -0
- data/src/apache2_module/DirConfig/AutoGeneratedManifestGeneration.cpp +11 -0
- data/src/apache2_module/DirConfig/AutoGeneratedMergeFunction.cpp +7 -0
- data/src/apache2_module/DirConfig/AutoGeneratedStruct.h +17 -0
- data/src/apache2_module/Hooks.cpp +0 -6
- data/src/cxx_supportlib/ConfigKit/IN_PRACTICE.md +2 -12
- data/src/cxx_supportlib/ConfigKit/Store.h +1 -6
- data/src/cxx_supportlib/Constants.h +1 -1
- data/src/cxx_supportlib/DataStructures/StringKeyTable.h +1 -7
- data/src/cxx_supportlib/Exceptions.cpp +178 -0
- data/src/cxx_supportlib/Exceptions.h +62 -177
- data/src/cxx_supportlib/IOTools/IOUtils.cpp +255 -228
- data/src/cxx_supportlib/IOTools/IOUtils.h +84 -121
- data/src/cxx_supportlib/ServerKit/Config.h +1 -6
- data/src/cxx_supportlib/ServerKit/FileBufferedChannel.h +1 -1
- data/src/cxx_supportlib/StaticString.h +1 -6
- data/src/cxx_supportlib/Utils/Curl.h +1 -6
- data/src/cxx_supportlib/Utils/ScopeGuard.h +0 -32
- data/src/cxx_supportlib/oxt/implementation.cpp +2 -2
- data/src/cxx_supportlib/oxt/spin_lock.hpp +94 -23
- data/src/ruby_supportlib/phusion_passenger/platform_info/compiler.rb +6 -10
- data/src/ruby_supportlib/phusion_passenger/platform_info/cxx_portability.rb +2 -2
- data/src/ruby_supportlib/phusion_passenger/rack_handler.rb +2 -2
- data/src/ruby_supportlib/phusion_passenger.rb +1 -1
- metadata +3 -7
- data/src/cxx_supportlib/oxt/detail/spin_lock_darwin.hpp +0 -75
- data/src/cxx_supportlib/oxt/detail/spin_lock_gcc_x86.hpp +0 -85
- data/src/cxx_supportlib/oxt/detail/spin_lock_portable.hpp +0 -38
- data/src/cxx_supportlib/oxt/detail/spin_lock_pthreads.hpp +0 -111
@@ -29,6 +29,7 @@
|
|
29
29
|
// https://bugzilla.redhat.com/show_bug.cgi?id=165427
|
30
30
|
// Also needed for SO_PEERCRED.
|
31
31
|
#define _GNU_SOURCE
|
32
|
+
#include <exception>
|
32
33
|
#endif
|
33
34
|
|
34
35
|
#include <oxt/system_calls.hpp>
|
@@ -86,18 +87,7 @@ using namespace oxt;
|
|
86
87
|
static WritevFunction writevFunction = syscalls::writev;
|
87
88
|
|
88
89
|
|
89
|
-
|
90
|
-
purgeStdio(FILE *f) {
|
91
|
-
#if defined(HAVE_FPURGE)
|
92
|
-
fpurge(f);
|
93
|
-
return true;
|
94
|
-
#elif defined(HAVE___FPURGE)
|
95
|
-
__fpurge(f);
|
96
|
-
return true;
|
97
|
-
#else
|
98
|
-
return false;
|
99
|
-
#endif
|
100
|
-
}
|
90
|
+
/****** Server address types support ******/
|
101
91
|
|
102
92
|
ServerAddressType
|
103
93
|
getSocketAddressType(const StaticString &address) {
|
@@ -182,67 +172,8 @@ isLocalSocketAddress(const StaticString &address) {
|
|
182
172
|
}
|
183
173
|
}
|
184
174
|
|
185
|
-
void
|
186
|
-
setBlocking(int fd) {
|
187
|
-
int flags, ret;
|
188
|
-
|
189
|
-
do {
|
190
|
-
flags = fcntl(fd, F_GETFL);
|
191
|
-
} while (flags == -1 && errno == EINTR);
|
192
|
-
if (flags == -1) {
|
193
|
-
int e = errno;
|
194
|
-
throw SystemException("Cannot set socket to blocking mode: "
|
195
|
-
"cannot get socket flags",
|
196
|
-
e);
|
197
|
-
}
|
198
|
-
do {
|
199
|
-
ret = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
|
200
|
-
} while (ret == -1 && errno == EINTR);
|
201
|
-
if (ret == -1) {
|
202
|
-
int e = errno;
|
203
|
-
throw SystemException("Cannot set socket to blocking mode: "
|
204
|
-
"cannot set socket flags",
|
205
|
-
e);
|
206
|
-
}
|
207
|
-
}
|
208
175
|
|
209
|
-
|
210
|
-
setNonBlocking(int fd) {
|
211
|
-
int flags, ret;
|
212
|
-
|
213
|
-
do {
|
214
|
-
flags = fcntl(fd, F_GETFL);
|
215
|
-
} while (flags == -1 && errno == EINTR);
|
216
|
-
if (flags == -1) {
|
217
|
-
int e = errno;
|
218
|
-
throw SystemException("Cannot set socket to non-blocking mode: "
|
219
|
-
"cannot get socket flags",
|
220
|
-
e);
|
221
|
-
}
|
222
|
-
do {
|
223
|
-
ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
224
|
-
} while (ret == -1 && errno == EINTR);
|
225
|
-
if (ret == -1) {
|
226
|
-
int e = errno;
|
227
|
-
throw SystemException("Cannot set socket to non-blocking mode: "
|
228
|
-
"cannot set socket flags",
|
229
|
-
e);
|
230
|
-
}
|
231
|
-
}
|
232
|
-
|
233
|
-
int
|
234
|
-
callAccept4(int sock, struct sockaddr *addr, socklen_t *addr_len, int options) {
|
235
|
-
#if defined(HAVE_ACCEPT4)
|
236
|
-
int ret;
|
237
|
-
do {
|
238
|
-
ret = ::accept4(sock, addr, addr_len, options);
|
239
|
-
} while (ret == -1 && errno == EINTR);
|
240
|
-
return ret;
|
241
|
-
#else
|
242
|
-
errno = ENOSYS;
|
243
|
-
return -1;
|
244
|
-
#endif
|
245
|
-
}
|
176
|
+
/****** Server socket creation ******/
|
246
177
|
|
247
178
|
int
|
248
179
|
createServer(const StaticString &address, unsigned int backlogSize, bool autoDelete,
|
@@ -285,7 +216,7 @@ createUnixServer(const StaticString &filename, unsigned int backlogSize, bool au
|
|
285
216
|
throw SystemException("Cannot create a Unix socket file descriptor", e);
|
286
217
|
}
|
287
218
|
|
288
|
-
FdGuard guard(fd, file, line
|
219
|
+
FdGuard guard(fd, file, line);
|
289
220
|
addr.sun_family = AF_LOCAL;
|
290
221
|
strncpy(addr.sun_path, filename.c_str(), filename.size());
|
291
222
|
addr.sun_path[filename.size()] = '\0';
|
@@ -376,7 +307,7 @@ createTcpServer(const char *address, unsigned short port, unsigned int backlogSi
|
|
376
307
|
}
|
377
308
|
// Ignore SO_REUSEADDR error, it's not fatal.
|
378
309
|
|
379
|
-
FdGuard guard(fd, file, line
|
310
|
+
FdGuard guard(fd, file, line);
|
380
311
|
if (family == AF_INET) {
|
381
312
|
ret = syscalls::bind(fd, (const struct sockaddr *) &addr.v4, sizeof(struct sockaddr_in));
|
382
313
|
} else {
|
@@ -408,6 +339,9 @@ createTcpServer(const char *address, unsigned short port, unsigned int backlogSi
|
|
408
339
|
return fd;
|
409
340
|
}
|
410
341
|
|
342
|
+
|
343
|
+
/****** Socket connection establishment (blocking) ******/
|
344
|
+
|
411
345
|
int
|
412
346
|
connectToServer(const StaticString &address, const char *file, unsigned int line) {
|
413
347
|
TRACE_POINT();
|
@@ -436,7 +370,7 @@ connectToUnixServer(const StaticString &filename, const char *file,
|
|
436
370
|
throw SystemException("Cannot create a Unix socket file descriptor", e);
|
437
371
|
}
|
438
372
|
|
439
|
-
FdGuard guard(fd, file, line
|
373
|
+
FdGuard guard(fd, file, line);
|
440
374
|
int ret;
|
441
375
|
struct sockaddr_un addr;
|
442
376
|
|
@@ -486,54 +420,6 @@ connectToUnixServer(const StaticString &filename, const char *file,
|
|
486
420
|
abort(); // Never reached.
|
487
421
|
}
|
488
422
|
|
489
|
-
void
|
490
|
-
setupNonBlockingUnixSocket(NUnix_State &state, const StaticString &filename,
|
491
|
-
const char *file, unsigned int line)
|
492
|
-
{
|
493
|
-
state.fd.assign(syscalls::socket(PF_UNIX, SOCK_STREAM, 0), file, line);
|
494
|
-
if (state.fd == -1) {
|
495
|
-
int e = errno;
|
496
|
-
throw SystemException("Cannot create a Unix socket file descriptor", e);
|
497
|
-
}
|
498
|
-
|
499
|
-
state.filename = filename;
|
500
|
-
setNonBlocking(state.fd);
|
501
|
-
}
|
502
|
-
|
503
|
-
bool
|
504
|
-
connectToUnixServer(NUnix_State &state) {
|
505
|
-
struct sockaddr_un addr;
|
506
|
-
int ret;
|
507
|
-
|
508
|
-
if (state.filename.size() > sizeof(addr.sun_path) - 1) {
|
509
|
-
string message = "Cannot connect to Unix socket '";
|
510
|
-
message.append(state.filename.data(), state.filename.size());
|
511
|
-
message.append("': filename is too long.");
|
512
|
-
throw RuntimeException(message);
|
513
|
-
}
|
514
|
-
|
515
|
-
addr.sun_family = AF_UNIX;
|
516
|
-
memcpy(addr.sun_path, state.filename.data(), state.filename.size());
|
517
|
-
addr.sun_path[state.filename.size()] = '\0';
|
518
|
-
|
519
|
-
ret = syscalls::connect(state.fd, (const sockaddr *) &addr, sizeof(addr));
|
520
|
-
if (ret == -1) {
|
521
|
-
if (errno == EINPROGRESS || errno == EWOULDBLOCK) {
|
522
|
-
return false;
|
523
|
-
} else if (errno == EISCONN) {
|
524
|
-
return true;
|
525
|
-
} else {
|
526
|
-
int e = errno;
|
527
|
-
string message = "Cannot connect to Unix socket '";
|
528
|
-
message.append(state.filename.data(), state.filename.size());
|
529
|
-
message.append("'");
|
530
|
-
throw SystemException(message, e);
|
531
|
-
}
|
532
|
-
} else {
|
533
|
-
return true;
|
534
|
-
}
|
535
|
-
}
|
536
|
-
|
537
423
|
int
|
538
424
|
connectToTcpServer(const StaticString &hostname, unsigned int port,
|
539
425
|
const char *file, unsigned int line)
|
@@ -591,145 +477,285 @@ connectToTcpServer(const StaticString &hostname, unsigned int port,
|
|
591
477
|
return fd;
|
592
478
|
}
|
593
479
|
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
480
|
+
|
481
|
+
/****** Socket connection establishment (non-blocking) ******/
|
482
|
+
|
483
|
+
std::pair<int, bool>
|
484
|
+
createNonBlockingSocketConnection(const StaticString &address, const char *file, unsigned int line) {
|
485
|
+
TRACE_POINT();
|
486
|
+
switch (getSocketAddressType(address)) {
|
487
|
+
case SAT_UNIX:
|
488
|
+
return createNonBlockingUnixSocketConnection(parseUnixSocketAddress(address), file, line);
|
489
|
+
case SAT_TCP: {
|
490
|
+
string host;
|
491
|
+
unsigned short port;
|
492
|
+
|
493
|
+
parseTcpSocketAddress(address, host, port);
|
494
|
+
return createNonBlockingTcpSocketConnection(host, port, file, line);
|
495
|
+
}
|
496
|
+
default:
|
497
|
+
throw ArgumentException(string("Unknown address type for '") + address + "'");
|
498
|
+
}
|
499
|
+
}
|
500
|
+
|
501
|
+
std::pair<int, bool>
|
502
|
+
createNonBlockingUnixSocketConnection(const StaticString &filename, const char *file, unsigned int line) {
|
503
|
+
struct sockaddr_un addr;
|
504
|
+
|
505
|
+
if (filename.size() > sizeof(addr.sun_path) - 1) {
|
506
|
+
string message = "Cannot connect to Unix socket '";
|
507
|
+
message.append(filename.data(), filename.size());
|
508
|
+
message.append("': filename is too long.");
|
509
|
+
throw ArgumentException(message);
|
510
|
+
}
|
511
|
+
|
512
|
+
|
513
|
+
int fd = syscalls::socket(PF_UNIX, SOCK_STREAM, 0);
|
514
|
+
if (fd == -1) {
|
515
|
+
int e = errno;
|
516
|
+
throw SystemException("Cannot create a Unix socket file descriptor", e);
|
517
|
+
}
|
518
|
+
|
598
519
|
int ret;
|
520
|
+
FdGuard guard(fd, nullptr, 0);
|
521
|
+
P_LOG_FILE_DESCRIPTOR_OPEN4(fd, file, line, "NonBlockingUnixSocketConnection");
|
522
|
+
setNonBlocking(fd);
|
599
523
|
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
524
|
+
addr.sun_family = AF_UNIX;
|
525
|
+
memcpy(addr.sun_path, filename.data(), filename.size());
|
526
|
+
addr.sun_path[filename.size()] = '\0';
|
527
|
+
|
528
|
+
ret = syscalls::connect(fd, (const sockaddr *) &addr, sizeof(addr));
|
529
|
+
if (ret == -1) {
|
530
|
+
if (errno == EINPROGRESS || errno == EWOULDBLOCK) {
|
531
|
+
guard.clear();
|
532
|
+
return std::make_pair(fd, false);
|
533
|
+
} else if (errno == EISCONN) {
|
534
|
+
guard.clear();
|
535
|
+
return std::make_pair(fd, true);
|
536
|
+
} else {
|
537
|
+
int e = errno;
|
538
|
+
string message = "Cannot connect to Unix socket '";
|
539
|
+
message.append(filename.data(), filename.size());
|
540
|
+
message.append("'");
|
541
|
+
throw SystemException(message, e);
|
542
|
+
}
|
543
|
+
} else {
|
544
|
+
guard.clear();
|
545
|
+
return std::make_pair(fd, true);
|
546
|
+
}
|
547
|
+
}
|
548
|
+
|
549
|
+
std::pair<int, bool>
|
550
|
+
createNonBlockingTcpSocketConnection(const StaticString &hostname, unsigned int port, const char *file, unsigned int line) {
|
551
|
+
const string hostnameCopy = string(hostname.data(), hostname.size());
|
552
|
+
const string portString = toString(port);
|
553
|
+
struct addrinfo hints, *res;
|
554
|
+
int ret;
|
555
|
+
|
556
|
+
memset(&hints, 0, sizeof(hints));
|
557
|
+
hints.ai_family = PF_UNSPEC;
|
558
|
+
hints.ai_socktype = SOCK_STREAM;
|
559
|
+
ret = getaddrinfo(hostnameCopy.c_str(), portString.c_str(),
|
560
|
+
&hints, &res);
|
605
561
|
if (ret != 0) {
|
606
562
|
string message = "Cannot resolve IP address '";
|
607
563
|
message.append(hostname.data(), hostname.size());
|
608
564
|
message.append(":");
|
609
|
-
message.append(
|
565
|
+
message.append(portString);
|
610
566
|
message.append("': ");
|
611
567
|
message.append(gai_strerror(ret));
|
612
568
|
throw IOException(message);
|
613
569
|
}
|
614
570
|
|
615
|
-
|
616
|
-
|
571
|
+
|
572
|
+
int fd = syscalls::socket(PF_INET, SOCK_STREAM, 0);
|
573
|
+
if (fd == -1) {
|
617
574
|
int e = errno;
|
618
575
|
throw SystemException("Cannot create a TCP socket file descriptor", e);
|
619
576
|
}
|
620
577
|
|
621
|
-
|
622
|
-
|
623
|
-
setNonBlocking(
|
624
|
-
}
|
578
|
+
FdGuard guard(fd, nullptr, 0);
|
579
|
+
P_LOG_FILE_DESCRIPTOR_OPEN4(fd, file, line, "NonBlockingTcpSocketConnection");
|
580
|
+
setNonBlocking(fd);
|
625
581
|
|
626
|
-
bool
|
627
|
-
connectToTcpServer(NTCP_State &state) {
|
628
|
-
int ret;
|
629
582
|
|
630
|
-
ret = syscalls::connect(
|
583
|
+
ret = syscalls::connect(fd, res->ai_addr, res->ai_addrlen);
|
631
584
|
if (ret == -1) {
|
632
585
|
if (errno == EINPROGRESS || errno == EWOULDBLOCK) {
|
633
|
-
|
586
|
+
guard.clear();
|
587
|
+
return make_pair(fd, false);
|
634
588
|
} else if (errno == EISCONN) {
|
635
|
-
freeaddrinfo(
|
636
|
-
|
637
|
-
return true;
|
589
|
+
freeaddrinfo(res);
|
590
|
+
guard.clear();
|
591
|
+
return make_pair(fd, true);
|
638
592
|
} else {
|
639
593
|
int e = errno;
|
640
594
|
string message = "Cannot connect to TCP socket '";
|
641
|
-
message.append(
|
595
|
+
message.append(hostname);
|
642
596
|
message.append(":");
|
643
|
-
message.append(
|
597
|
+
message.append(portString);
|
644
598
|
message.append("'");
|
645
599
|
throw SystemException(message, e);
|
646
600
|
}
|
647
601
|
} else {
|
648
|
-
freeaddrinfo(
|
649
|
-
|
650
|
-
return true;
|
602
|
+
freeaddrinfo(res);
|
603
|
+
guard.clear();
|
604
|
+
return make_pair(fd, true);
|
651
605
|
}
|
652
606
|
}
|
653
607
|
|
654
|
-
|
608
|
+
|
609
|
+
/****** Scope guards ******/
|
610
|
+
|
611
|
+
FdGuard::FdGuard(FdGuard &&other)
|
612
|
+
: mFd(other.mFd)
|
655
613
|
{
|
656
|
-
|
657
|
-
|
658
|
-
switch (type) {
|
659
|
-
case SAT_UNIX:
|
660
|
-
setupNonBlockingUnixSocket(s_unix, parseUnixSocketAddress(address),
|
661
|
-
file, line);
|
662
|
-
break;
|
663
|
-
case SAT_TCP: {
|
664
|
-
string host;
|
665
|
-
unsigned short port;
|
614
|
+
other.mFd = -1;
|
615
|
+
}
|
666
616
|
|
667
|
-
|
668
|
-
|
669
|
-
|
617
|
+
FdGuard::FdGuard(int fd, const char *sourceFile, unsigned int sourceLine)
|
618
|
+
: mFd(fd)
|
619
|
+
{
|
620
|
+
if (mFd != -1 && sourceFile != nullptr) {
|
621
|
+
P_LOG_FILE_DESCRIPTOR_OPEN3(fd, sourceFile, sourceLine);
|
670
622
|
}
|
671
|
-
|
672
|
-
|
623
|
+
}
|
624
|
+
|
625
|
+
FdGuard::~FdGuard() noexcept(false) {
|
626
|
+
if (mFd != -1) {
|
627
|
+
try {
|
628
|
+
safelyClose(mFd);
|
629
|
+
} catch (const std::exception &e) {
|
630
|
+
bool uncaughtException =
|
631
|
+
#if __cplusplus >= 201703L
|
632
|
+
std::uncaught_exceptions() > 0;
|
633
|
+
#else
|
634
|
+
std::uncaught_exception();
|
635
|
+
#endif
|
636
|
+
if (uncaughtException) {
|
637
|
+
P_WARN("Error closing file descriptor " << mFd << ": " << e.what());
|
638
|
+
return;
|
639
|
+
} else {
|
640
|
+
throw e;
|
641
|
+
}
|
642
|
+
}
|
643
|
+
P_LOG_FILE_DESCRIPTOR_CLOSE(mFd);
|
673
644
|
}
|
674
645
|
}
|
675
646
|
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
647
|
+
FdGuard &
|
648
|
+
FdGuard::operator=(FdGuard &&other) {
|
649
|
+
if (this != &other) {
|
650
|
+
if (mFd != -1) {
|
651
|
+
safelyClose(mFd);
|
652
|
+
P_LOG_FILE_DESCRIPTOR_CLOSE(mFd);
|
653
|
+
}
|
654
|
+
mFd = other.mFd;
|
655
|
+
other.mFd = -1;
|
685
656
|
}
|
657
|
+
return *this;
|
686
658
|
}
|
687
659
|
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
660
|
+
void
|
661
|
+
FdGuard::clear() noexcept {
|
662
|
+
mFd = -1;
|
663
|
+
}
|
664
|
+
|
665
|
+
void
|
666
|
+
FdGuard::runNow() noexcept(false) {
|
667
|
+
if (mFd != -1) {
|
668
|
+
safelyClose(mFd);
|
669
|
+
P_LOG_FILE_DESCRIPTOR_CLOSE(mFd);
|
670
|
+
mFd = -1;
|
697
671
|
}
|
698
672
|
}
|
699
673
|
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
674
|
+
|
675
|
+
/****** Other ******/
|
676
|
+
|
677
|
+
bool
|
678
|
+
purgeStdio(FILE *f) {
|
679
|
+
#if defined(HAVE_FPURGE)
|
680
|
+
fpurge(f);
|
681
|
+
return true;
|
682
|
+
#elif defined(HAVE___FPURGE)
|
683
|
+
__fpurge(f);
|
684
|
+
return true;
|
685
|
+
#else
|
686
|
+
return false;
|
687
|
+
#endif
|
709
688
|
}
|
710
689
|
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
690
|
+
void
|
691
|
+
setBlocking(int fd) {
|
692
|
+
int flags, ret;
|
693
|
+
|
694
|
+
do {
|
695
|
+
flags = fcntl(fd, F_GETFL);
|
696
|
+
} while (flags == -1 && errno == EINTR);
|
697
|
+
if (flags == -1) {
|
698
|
+
int e = errno;
|
699
|
+
throw SystemException("Cannot set socket to blocking mode: "
|
700
|
+
"cannot get socket flags",
|
701
|
+
e);
|
702
|
+
}
|
703
|
+
do {
|
704
|
+
ret = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
|
705
|
+
} while (ret == -1 && errno == EINTR);
|
706
|
+
if (ret == -1) {
|
707
|
+
int e = errno;
|
708
|
+
throw SystemException("Cannot set socket to blocking mode: "
|
709
|
+
"cannot set socket flags",
|
710
|
+
e);
|
711
|
+
}
|
712
|
+
}
|
713
|
+
|
714
|
+
void
|
715
|
+
setNonBlocking(int fd) {
|
716
|
+
int flags, ret;
|
717
|
+
|
718
|
+
do {
|
719
|
+
flags = fcntl(fd, F_GETFL);
|
720
|
+
} while (flags == -1 && errno == EINTR);
|
721
|
+
if (flags == -1) {
|
722
|
+
int e = errno;
|
723
|
+
throw SystemException("Cannot set socket to non-blocking mode: "
|
724
|
+
"cannot get socket flags",
|
725
|
+
e);
|
726
|
+
}
|
727
|
+
do {
|
728
|
+
ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
729
|
+
} while (ret == -1 && errno == EINTR);
|
730
|
+
if (ret == -1) {
|
731
|
+
int e = errno;
|
732
|
+
throw SystemException("Cannot set socket to non-blocking mode: "
|
733
|
+
"cannot set socket flags",
|
734
|
+
e);
|
735
|
+
}
|
736
|
+
}
|
737
|
+
|
738
|
+
int
|
739
|
+
callAccept4(int sock, struct sockaddr *addr, socklen_t *addr_len, int options) {
|
740
|
+
#if defined(HAVE_ACCEPT4)
|
741
|
+
int ret;
|
742
|
+
do {
|
743
|
+
ret = ::accept4(sock, addr, addr_len, options);
|
744
|
+
} while (ret == -1 && errno == EINTR);
|
745
|
+
return ret;
|
746
|
+
#else
|
747
|
+
errno = ENOSYS;
|
748
|
+
return -1;
|
749
|
+
#endif
|
720
750
|
}
|
721
751
|
|
722
752
|
bool
|
723
753
|
pingTcpServer(const StaticString &host, unsigned int port, unsigned long long *timeout) {
|
724
754
|
TRACE_POINT();
|
725
|
-
|
726
|
-
|
727
|
-
setupNonBlockingTcpSocket(state, host, port, __FILE__, __LINE__);
|
755
|
+
std::pair<int, bool> nbcResult;
|
728
756
|
|
729
757
|
try {
|
730
|
-
|
731
|
-
return true;
|
732
|
-
}
|
758
|
+
nbcResult = createNonBlockingTcpSocketConnection(host, port, __FILE__, __LINE__);
|
733
759
|
} catch (const SystemException &e) {
|
734
760
|
if (e.code() == ECONNREFUSED) {
|
735
761
|
return false;
|
@@ -737,13 +763,17 @@ pingTcpServer(const StaticString &host, unsigned int port, unsigned long long *t
|
|
737
763
|
throw e;
|
738
764
|
}
|
739
765
|
}
|
766
|
+
FdGuard guard(nbcResult.first, nullptr, 0);
|
767
|
+
if (nbcResult.second) {
|
768
|
+
return true;
|
769
|
+
}
|
740
770
|
|
741
771
|
// Cannot connect to the port yet, but that may not mean the
|
742
772
|
// port is unavailable. So poll the socket.
|
743
773
|
|
744
774
|
bool connectable;
|
745
775
|
try {
|
746
|
-
connectable = waitUntilWritable(
|
776
|
+
connectable = waitUntilWritable(nbcResult.first, timeout);
|
747
777
|
} catch (const SystemException &e) {
|
748
778
|
throw SystemException("Error polling TCP socket "
|
749
779
|
+ host + ":" + toString(port), e.code());
|
@@ -753,24 +783,21 @@ pingTcpServer(const StaticString &host, unsigned int port, unsigned long long *t
|
|
753
783
|
return false;
|
754
784
|
}
|
755
785
|
|
756
|
-
//
|
786
|
+
// Now check the final connection establishment status.
|
757
787
|
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
} else {
|
772
|
-
throw e;
|
773
|
-
}
|
788
|
+
int connectError = 0;
|
789
|
+
socklen_t connectErrorLen = sizeof(connectError);
|
790
|
+
if (getsockopt(nbcResult.first, SOL_SOCKET, SO_ERROR, &connectError, &connectErrorLen) == -1) {
|
791
|
+
throw SystemException("Error checking TCP socket " + host + ":" + toString(port)
|
792
|
+
+ " connection establishment status", connectError);
|
793
|
+
}
|
794
|
+
if (connectError == 0) {
|
795
|
+
return true;
|
796
|
+
} else if (connectError == ECONNREFUSED) {
|
797
|
+
return false;
|
798
|
+
} else {
|
799
|
+
throw SystemException("Error connecting to TCP socket " + host + ":"
|
800
|
+
+ toString(port), connectError);
|
774
801
|
}
|
775
802
|
}
|
776
803
|
|