Skip to content

Commit 785c0b6

Browse files
kwvgUdjinM6
andcommitted
chore: remove scaffolding (remove default args, make explicit choice)
This was acceptable while we were refining earlier commits but default args could in combination with future backports result in behavior changes that were unanticipated, we should clear the air right now. We are introducing a new global, `g_socket_events_mode` to allow us to influence Wait(Many)() calls as and when needed. A global is acceptable as it's lightweight, a parameter that is not configurable during runtime except during initial startup and because the structure in which it is ordinarily stored is far heavier. Co-authored-by: UdjinM6 <[email protected]>
1 parent 2959594 commit 785c0b6

File tree

11 files changed

+68
-44
lines changed

11 files changed

+68
-44
lines changed

src/i2p.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ bool Session::Accept(Connection& conn)
160160

161161
while (!*m_interrupt) {
162162
Sock::Event occurred;
163-
if (!conn.sock->Wait(MAX_WAIT_FOR_IO, Sock::RECV, SocketEventsParams(), &occurred)) {
163+
if (!conn.sock->Wait(MAX_WAIT_FOR_IO, Sock::RECV, SocketEventsParams{::g_socket_events_mode}, &occurred)) {
164164
errmsg = "wait on socket failed";
165165
break;
166166
}

src/init.cpp

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -480,21 +480,6 @@ static void OnRPCStopped()
480480
LogPrint(BCLog::RPC, "RPC stopped.\n");
481481
}
482482

483-
std::string GetSupportedSocketEventsStr()
484-
{
485-
std::string strSupportedModes = "'select'";
486-
#ifdef USE_POLL
487-
strSupportedModes += ", 'poll'";
488-
#endif
489-
#ifdef USE_EPOLL
490-
strSupportedModes += ", 'epoll'";
491-
#endif
492-
#ifdef USE_KQUEUE
493-
strSupportedModes += ", 'kqueue'";
494-
#endif
495-
return strSupportedModes;
496-
}
497-
498483
void SetupServerArgs(ArgsManager& argsman)
499484
{
500485
SetupHelpOptions(argsman);
@@ -2533,6 +2518,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
25332518
return InitError(strprintf(_("Invalid -socketevents ('%s') specified. Only these modes are supported: %s"), sem_str, GetSupportedSocketEventsStr()));
25342519
}
25352520
connOptions.socketEventsMode = sem;
2521+
::g_socket_events_mode = sem;
25362522

25372523
const std::string& i2psam_arg = args.GetArg("-i2psam", "");
25382524
if (!i2psam_arg.empty()) {

src/masternode/node.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ void CActiveMasternodeManager::InitInternal(const CBlockIndex* pindex)
156156
// Check socket connectivity
157157
LogPrintf("CActiveMasternodeManager::Init -- Checking inbound connection to '%s'\n", m_info.service.ToStringAddrPort());
158158
std::unique_ptr<Sock> sock{ConnectDirectly(m_info.service, /*manual_connection=*/true)};
159-
bool fConnected{sock && sock->IsSelectable()};
159+
bool fConnected{sock && sock->IsSelectable(/*is_select=*/::g_socket_events_mode == SocketEventsMode::Select)};
160160
sock = std::make_unique<Sock>(INVALID_SOCKET);
161161
if (!fConnected && Params().RequireRoutableExternalIP()) {
162162
m_state = MasternodeState::SOME_ERROR;

src/net.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1928,7 +1928,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
19281928
return;
19291929
}
19301930

1931-
if (!sock->IsSelectable()) {
1931+
if (!sock->IsSelectable(/*is_select=*/::g_socket_events_mode == SocketEventsMode::Select)) {
19321932
LogPrintf("%s: non-selectable socket\n", strDropped);
19331933
return;
19341934
}

src/netbase.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, c
336336
// we're approaching the end of the specified total timeout
337337
const auto remaining = std::chrono::milliseconds{endTime - curTime};
338338
const auto timeout = std::min(remaining, std::chrono::milliseconds{MAX_WAIT_FOR_IO});
339-
if (!sock.Wait(timeout, Sock::RECV)) {
339+
if (!sock.Wait(timeout, Sock::RECV, SocketEventsParams{::g_socket_events_mode})) {
340340
return IntrRecvError::NetworkError;
341341
}
342342
} else {
@@ -514,7 +514,7 @@ std::unique_ptr<Sock> CreateSockOS(sa_family_t address_family)
514514

515515
// Ensure that waiting for I/O on this socket won't result in undefined
516516
// behavior.
517-
if (!sock->IsSelectable()) {
517+
if (!sock->IsSelectable(/*is_select=*/::g_socket_events_mode == SocketEventsMode::Select)) {
518518
LogPrintf("Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n");
519519
return nullptr;
520520
}
@@ -572,7 +572,7 @@ static bool ConnectToSocket(const Sock& sock, struct sockaddr* sockaddr, socklen
572572
// synchronously to check for successful connection with a timeout.
573573
const Sock::Event requested = Sock::RECV | Sock::SEND;
574574
Sock::Event occurred;
575-
if (!sock.Wait(std::chrono::milliseconds{nConnectTimeout}, requested, SocketEventsParams(), &occurred)) {
575+
if (!sock.Wait(std::chrono::milliseconds{nConnectTimeout}, requested, SocketEventsParams{::g_socket_events_mode}, &occurred)) {
576576
LogPrintf("wait for connect to %s failed: %s\n",
577577
dest_str,
578578
NetworkErrorString(WSAGetLastError()));

src/test/fuzz/util.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ class FuzzedSock : public Sock
8989

9090
bool IsSelectable(bool is_select) const override;
9191

92-
bool Wait(std::chrono::milliseconds timeout, Event requested, SocketEventsParams event_params = SocketEventsParams(), Event* occurred = nullptr) const override;
92+
bool Wait(std::chrono::milliseconds timeout, Event requested, SocketEventsParams event_params, Event* occurred = nullptr) const override;
9393

94-
bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock, SocketEventsParams event_params = SocketEventsParams()) const override;
94+
bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock, SocketEventsParams event_params) const override;
9595

9696
bool IsConnected(std::string& errmsg) const override;
9797
};

src/test/sock_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ BOOST_AUTO_TEST_CASE(wait)
121121
Sock sock0(s[0]);
122122
Sock sock1(s[1]);
123123

124-
std::thread waiter([&sock0]() { (void)sock0.Wait(24h, Sock::RECV); });
124+
std::thread waiter([&sock0]() { (void)sock0.Wait(24h, Sock::RECV, SocketEventsParams{::g_socket_events_mode}); });
125125

126126
BOOST_REQUIRE_EQUAL(sock1.Send("a", 1, 0), 1);
127127

src/test/util/net.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ class StaticContentsSock : public Sock
202202

203203
bool Wait(std::chrono::milliseconds timeout,
204204
Event requested,
205-
SocketEventsParams event_params = SocketEventsParams(),
205+
SocketEventsParams event_params,
206206
Event* occurred = nullptr) const override
207207
{
208208
if (occurred != nullptr) {
@@ -213,7 +213,7 @@ class StaticContentsSock : public Sock
213213

214214
bool WaitMany(std::chrono::milliseconds timeout,
215215
EventsPerSock& events_per_sock,
216-
SocketEventsParams event_params = SocketEventsParams()) const override
216+
SocketEventsParams event_params) const override
217217
{
218218
for (auto& [sock, events] : events_per_sock) {
219219
(void)sock;

src/test/util/setup_common.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,15 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::ve
189189
m_node.addrman = std::make_unique<AddrMan>(*m_node.netgroupman,
190190
/*deterministic=*/false,
191191
m_node.args->GetIntArg("-checkaddrman", 0));
192+
193+
std::string sem_str = m_args.GetArg("-socketevents", DEFAULT_SOCKETEVENTS);
194+
::g_socket_events_mode = SEMFromString(sem_str);
195+
if (::g_socket_events_mode == SocketEventsMode::Unknown) {
196+
throw std::runtime_error(
197+
strprintf("Invalid -socketevents ('%s') specified. Only these modes are supported: %s",
198+
sem_str, GetSupportedSocketEventsStr()));
199+
}
200+
192201
m_node.connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman, *m_node.netgroupman); // Deterministic randomness for tests.
193202

194203
fCheckBlockIndex = true;
@@ -209,6 +218,7 @@ BasicTestingSetup::~BasicTestingSetup()
209218
m_node.cpoolman.reset();
210219
m_node.mnhf_manager.reset();
211220
m_node.evodb.reset();
221+
::g_socket_events_mode = SocketEventsMode::Unknown;
212222
m_node.connman.reset();
213223
m_node.addrman.reset();
214224
m_node.netgroupman.reset();
@@ -326,6 +336,7 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
326336
{
327337
CConnman::Options options;
328338
options.m_msgproc = m_node.peerman.get();
339+
options.socketEventsMode = ::g_socket_events_mode;
329340
m_node.connman->Init(options);
330341
}
331342

src/util/sock.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#include <poll.h>
3333
#endif
3434

35+
SocketEventsMode g_socket_events_mode{SocketEventsMode::Unknown};
36+
3537
static inline bool IOErrorIsPermanent(int err)
3638
{
3739
return err != WSAEAGAIN && err != WSAEINTR && err != WSAEWOULDBLOCK && err != WSAEINPROGRESS;
@@ -162,10 +164,17 @@ bool Sock::Wait(std::chrono::milliseconds timeout, Event requested, SocketEvents
162164
{
163165
EventsPerSock events_per_sock{std::make_pair(m_socket, Events{requested})};
164166

167+
// We need to ensure we are only using a level-triggered mode because we are expecting
168+
// a direct correlation between the events reported and the one socket we are querying
165169
if (auto [sem, _, __] = event_params; sem != SocketEventsMode::Poll && sem != SocketEventsMode::Select) {
166-
// We need to ensure we are only using a level-triggered mode because we are expecting
167-
// a direct correlation between the events reported and the one socket we are querying
168-
event_params = SocketEventsParams();
170+
// We will use a compatible fallback events mode if we didn't specify a valid option
171+
event_params = SocketEventsParams{
172+
#ifdef USE_POLL
173+
SocketEventsMode::Poll
174+
#else
175+
SocketEventsMode::Select
176+
#endif /* USE_POLL */
177+
};
169178
}
170179
if (!WaitMany(timeout, events_per_sock, event_params)) {
171180
return false;
@@ -435,7 +444,7 @@ void Sock::SendComplete(const std::string& data,
435444
// Wait for a short while (or the socket to become ready for sending) before retrying
436445
// if nothing was sent.
437446
const auto wait_time = std::min(deadline - now, std::chrono::milliseconds{MAX_WAIT_FOR_IO});
438-
(void)Wait(wait_time, SEND);
447+
(void)Wait(wait_time, SEND, SocketEventsParams{::g_socket_events_mode});
439448
}
440449
}
441450

@@ -518,7 +527,7 @@ std::string Sock::RecvUntilTerminator(uint8_t terminator,
518527

519528
// Wait for a short while (or the socket to become ready for reading) before retrying.
520529
const auto wait_time = std::min(deadline - now, std::chrono::milliseconds{MAX_WAIT_FOR_IO});
521-
(void)Wait(wait_time, RECV);
530+
(void)Wait(wait_time, RECV, SocketEventsParams{::g_socket_events_mode});
522531
}
523532
}
524533

0 commit comments

Comments
 (0)