Skip to content

Commit 212df06

Browse files
committed
refactor: introduce EdgeTriggeredEvents, move {epoll, kqueue} fd there
1 parent 3b11ef9 commit 212df06

File tree

5 files changed

+131
-51
lines changed

5 files changed

+131
-51
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ BITCOIN_CORE_H = \
327327
util/bip32.h \
328328
util/bytevectorhash.h \
329329
util/check.h \
330+
util/edge.h \
330331
util/enumerate.h \
331332
util/epochguard.h \
332333
util/error.h \
@@ -776,6 +777,7 @@ libbitcoin_util_a_SOURCES = \
776777
util/bip32.cpp \
777778
util/bytevectorhash.cpp \
778779
util/check.cpp \
780+
util/edge.cpp \
779781
util/error.cpp \
780782
util/fees.cpp \
781783
util/hasher.cpp \

src/net.cpp

Lines changed: 31 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1588,7 +1588,7 @@ void CConnman::SocketEventsKqueue(std::set<SOCKET>& recv_set,
15881588
timeout.tv_nsec = (only_poll ? 0 : SELECT_TIMEOUT_MILLISECONDS % 1000) * 1000 * 1000;
15891589

15901590
wakeupSelectNeeded = true;
1591-
int n = kevent(kqueuefd, nullptr, 0, events, maxEvents, &timeout);
1591+
int n = kevent(Assert(m_edge_trig_events)->m_fd, nullptr, 0, events, maxEvents, &timeout);
15921592
wakeupSelectNeeded = false;
15931593
if (n == -1) {
15941594
LogPrintf("kevent wait error\n");
@@ -1622,7 +1622,7 @@ void CConnman::SocketEventsEpoll(std::set<SOCKET>& recv_set,
16221622
epoll_event events[maxEvents];
16231623

16241624
wakeupSelectNeeded = true;
1625-
int n = epoll_wait(epollfd, events, maxEvents, only_poll ? 0 : SELECT_TIMEOUT_MILLISECONDS);
1625+
int n = epoll_wait(Assert(m_edge_trig_events)->m_fd, events, maxEvents, only_poll ? 0 : SELECT_TIMEOUT_MILLISECONDS);
16261626
wakeupSelectNeeded = false;
16271627
for (int i = 0; i < n; i++) {
16281628
auto& e = events[i];
@@ -3136,8 +3136,8 @@ bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError,
31363136
if (socketEventsMode == SocketEventsMode::KQueue) {
31373137
struct kevent event;
31383138
EV_SET(&event, sock->Get(), EVFILT_READ, EV_ADD, 0, 0, nullptr);
3139-
if (kevent(kqueuefd, &event, 1, nullptr, 0, nullptr) != 0) {
3140-
strError = strprintf(_("Error: failed to add socket to kqueuefd (kevent returned error %s)"), NetworkErrorString(WSAGetLastError()));
3139+
if (kevent(Assert(m_edge_trig_events)->m_fd, &event, 1, nullptr, 0, nullptr) != 0) {
3140+
strError = strprintf(_("Error: failed to add socket to kqueue fd (kevent returned error %s)"), NetworkErrorString(WSAGetLastError()));
31413141
LogPrintf("%s\n", strError.original);
31423142
return false;
31433143
}
@@ -3149,8 +3149,8 @@ bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError,
31493149
epoll_event event;
31503150
event.data.fd = sock->Get();
31513151
event.events = EPOLLIN;
3152-
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sock->Get(), &event) != 0) {
3153-
strError = strprintf(_("Error: failed to add socket to epollfd (epoll_ctl returned error %s)"), NetworkErrorString(WSAGetLastError()));
3152+
if (epoll_ctl(Assert(m_edge_trig_events)->m_fd, EPOLL_CTL_ADD, sock->Get(), &event) != 0) {
3153+
strError = strprintf(_("Error: failed to add socket to epoll fd (epoll_ctl returned error %s)"), NetworkErrorString(WSAGetLastError()));
31543154
LogPrintf("%s\n", strError.original);
31553155
return false;
31563156
}
@@ -3301,25 +3301,14 @@ bool CConnman::Start(CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_met
33013301
AssertLockNotHeld(m_total_bytes_sent_mutex);
33023302
Init(connOptions);
33033303

3304-
#ifdef USE_KQUEUE
3305-
if (socketEventsMode == SocketEventsMode::KQueue) {
3306-
kqueuefd = kqueue();
3307-
if (kqueuefd == -1) {
3308-
LogPrintf("kqueue failed\n");
3309-
return false;
3310-
}
3311-
}
3312-
#endif
3313-
3314-
#ifdef USE_EPOLL
3315-
if (socketEventsMode == SocketEventsMode::EPoll) {
3316-
epollfd = epoll_create1(0);
3317-
if (epollfd == -1) {
3318-
LogPrintf("epoll_create1 failed\n");
3304+
if (socketEventsMode == SocketEventsMode::EPoll || socketEventsMode == SocketEventsMode::KQueue) {
3305+
m_edge_trig_events = std::make_unique<EdgeTriggeredEvents>(socketEventsMode);
3306+
if (!m_edge_trig_events->IsValid()) {
3307+
LogPrintf("Unable to initialize EdgeTriggeredEvents instance\n");
3308+
m_edge_trig_events.reset();
33193309
return false;
33203310
}
33213311
}
3322-
#endif
33233312

33243313
if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds, connOptions.onion_binds)) {
33253314
if (clientInterface) {
@@ -3408,10 +3397,10 @@ bool CConnman::Start(CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_met
34083397
if (socketEventsMode == SocketEventsMode::KQueue) {
34093398
struct kevent event;
34103399
EV_SET(&event, wakeupPipe[0], EVFILT_READ, EV_ADD, 0, 0, nullptr);
3411-
int r = kevent(kqueuefd, &event, 1, nullptr, 0, nullptr);
3400+
int r = kevent(Assert(m_edge_trig_events)->m_fd, &event, 1, nullptr, 0, nullptr);
34123401
if (r != 0) {
34133402
LogPrint(BCLog::NET, "%s -- kevent(%d, %d, %d, ...) failed. error: %s\n", __func__,
3414-
kqueuefd, EV_ADD, wakeupPipe[0], NetworkErrorString(WSAGetLastError()));
3403+
m_edge_trig_events->m_fd, EV_ADD, wakeupPipe[0], NetworkErrorString(WSAGetLastError()));
34153404
return false;
34163405
}
34173406
}
@@ -3421,10 +3410,10 @@ bool CConnman::Start(CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_met
34213410
epoll_event event;
34223411
event.events = EPOLLIN;
34233412
event.data.fd = wakeupPipe[0];
3424-
int r = epoll_ctl(epollfd, EPOLL_CTL_ADD, wakeupPipe[0], &event);
3413+
int r = epoll_ctl(Assert(m_edge_trig_events)->m_fd, EPOLL_CTL_ADD, wakeupPipe[0], &event);
34253414
if (r != 0) {
34263415
LogPrint(BCLog::NET, "%s -- epoll_ctl(%d, %d, %d, ...) failed. error: %s\n", __func__,
3427-
epollfd, EPOLL_CTL_ADD, wakeupPipe[0], NetworkErrorString(WSAGetLastError()));
3416+
m_edge_trig_events->m_fd, EPOLL_CTL_ADD, wakeupPipe[0], NetworkErrorString(WSAGetLastError()));
34283417
return false;
34293418
}
34303419
}
@@ -3570,12 +3559,12 @@ void CConnman::StopNodes()
35703559
if (socketEventsMode == SocketEventsMode::KQueue) {
35713560
struct kevent event;
35723561
EV_SET(&event, hListenSocket.socket, EVFILT_READ, EV_DELETE, 0, 0, nullptr);
3573-
kevent(kqueuefd, &event, 1, nullptr, 0, nullptr);
3562+
kevent(Assert(m_edge_trig_events)->m_fd, &event, 1, nullptr, 0, nullptr);
35743563
}
35753564
#endif
35763565
#ifdef USE_EPOLL
35773566
if (socketEventsMode == SocketEventsMode::EPoll) {
3578-
epoll_ctl(epollfd, EPOLL_CTL_DEL, hListenSocket.socket, nullptr);
3567+
epoll_ctl(Assert(m_edge_trig_events)->m_fd, EPOLL_CTL_DEL, hListenSocket.socket, nullptr);
35793568
}
35803569
#endif
35813570
if (!CloseSocket(hListenSocket.socket))
@@ -3606,24 +3595,22 @@ void CConnman::StopNodes()
36063595
semAddnode.reset();
36073596

36083597
#ifdef USE_KQUEUE
3609-
if (socketEventsMode == SocketEventsMode::KQueue && kqueuefd != -1) {
3598+
if (socketEventsMode == SocketEventsMode::KQueue && Assert(m_edge_trig_events)->m_fd != -1) {
36103599
#ifdef USE_WAKEUP_PIPE
36113600
struct kevent event;
36123601
EV_SET(&event, wakeupPipe[0], EVFILT_READ, EV_DELETE, 0, 0, nullptr);
3613-
kevent(kqueuefd, &event, 1, nullptr, 0, nullptr);
3602+
kevent(m_edge_trig_events->m_fd, &event, 1, nullptr, 0, nullptr);
36143603
#endif
3615-
close(kqueuefd);
3604+
m_edge_trig_events.reset();
36163605
}
3617-
kqueuefd = -1;
36183606
#endif
36193607
#ifdef USE_EPOLL
3620-
if (socketEventsMode == SocketEventsMode::EPoll && epollfd != -1) {
3608+
if (socketEventsMode == SocketEventsMode::EPoll && Assert(m_edge_trig_events)->m_fd != -1) {
36213609
#ifdef USE_WAKEUP_PIPE
3622-
epoll_ctl(epollfd, EPOLL_CTL_DEL, wakeupPipe[0], nullptr);
3610+
epoll_ctl(m_edge_trig_events->m_fd, EPOLL_CTL_DEL, wakeupPipe[0], nullptr);
36233611
#endif
3624-
close(epollfd);
3612+
m_edge_trig_events.reset();
36253613
}
3626-
epollfd = -1;
36273614
#endif
36283615

36293616
#ifdef USE_WAKEUP_PIPE
@@ -4245,10 +4232,10 @@ void CConnman::RegisterEvents(CNode *pnode)
42454232
EV_SET(&events[0], pnode->hSocket, EVFILT_READ, EV_ADD, 0, 0, nullptr);
42464233
EV_SET(&events[1], pnode->hSocket, EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, nullptr);
42474234

4248-
int r = kevent(kqueuefd, events, 2, nullptr, 0, nullptr);
4235+
int r = kevent(Assert(m_edge_trig_events)->m_fd, events, 2, nullptr, 0, nullptr);
42494236
if (r != 0) {
42504237
LogPrint(BCLog::NET, "%s -- kevent(%d, %d, %d, ...) failed. error: %s\n", __func__,
4251-
kqueuefd, EV_ADD, pnode->hSocket, NetworkErrorString(WSAGetLastError()));
4238+
m_edge_trig_events->m_fd, EV_ADD, pnode->hSocket, NetworkErrorString(WSAGetLastError()));
42524239
}
42534240
}
42544241
#endif
@@ -4262,10 +4249,10 @@ void CConnman::RegisterEvents(CNode *pnode)
42624249
e.events = EPOLLIN | EPOLLOUT | EPOLLET | EPOLLERR | EPOLLHUP;
42634250
e.data.fd = pnode->hSocket;
42644251

4265-
int r = epoll_ctl(epollfd, EPOLL_CTL_ADD, pnode->hSocket, &e);
4252+
int r = epoll_ctl(Assert(m_edge_trig_events)->m_fd, EPOLL_CTL_ADD, pnode->hSocket, &e);
42664253
if (r != 0) {
42674254
LogPrint(BCLog::NET, "%s -- epoll_ctl(%d, %d, %d, ...) failed. error: %s\n", __func__,
4268-
epollfd, EPOLL_CTL_ADD, pnode->hSocket, NetworkErrorString(WSAGetLastError()));
4255+
m_edge_trig_events->m_fd, EPOLL_CTL_ADD, pnode->hSocket, NetworkErrorString(WSAGetLastError()));
42694256
}
42704257
}
42714258
#endif
@@ -4284,10 +4271,10 @@ void CConnman::UnregisterEvents(CNode *pnode)
42844271
EV_SET(&events[0], pnode->hSocket, EVFILT_READ, EV_DELETE, 0, 0, nullptr);
42854272
EV_SET(&events[1], pnode->hSocket, EVFILT_WRITE, EV_DELETE, 0, 0, nullptr);
42864273

4287-
int r = kevent(kqueuefd, events, 2, nullptr, 0, nullptr);
4274+
int r = kevent(Assert(m_edge_trig_events)->m_fd, events, 2, nullptr, 0, nullptr);
42884275
if (r != 0) {
42894276
LogPrint(BCLog::NET, "%s -- kevent(%d, %d, %d, ...) failed. error: %s\n", __func__,
4290-
kqueuefd, EV_DELETE, pnode->hSocket, NetworkErrorString(WSAGetLastError()));
4277+
m_edge_trig_events->m_fd, EV_DELETE, pnode->hSocket, NetworkErrorString(WSAGetLastError()));
42914278
}
42924279
}
42934280
#endif
@@ -4298,10 +4285,10 @@ void CConnman::UnregisterEvents(CNode *pnode)
42984285
return;
42994286
}
43004287

4301-
int r = epoll_ctl(epollfd, EPOLL_CTL_DEL, pnode->hSocket, nullptr);
4288+
int r = epoll_ctl(Assert(m_edge_trig_events)->m_fd, EPOLL_CTL_DEL, pnode->hSocket, nullptr);
43024289
if (r != 0) {
43034290
LogPrint(BCLog::NET, "%s -- epoll_ctl(%d, %d, %d, ...) failed. error: %s\n", __func__,
4304-
epollfd, EPOLL_CTL_DEL, pnode->hSocket, NetworkErrorString(WSAGetLastError()));
4291+
m_edge_trig_events->m_fd, EPOLL_CTL_DEL, pnode->hSocket, NetworkErrorString(WSAGetLastError()));
43054292
}
43064293
}
43074294
#endif

src/net.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@
2828
#include <sync.h>
2929
#include <threadinterrupt.h>
3030
#include <uint256.h>
31+
#include <util/check.h>
32+
#include <util/edge.h>
3133
#include <util/system.h>
3234
#include <consensus/params.h>
33-
#include <util/check.h>
3435

3536
#include <atomic>
3637
#include <condition_variable>
@@ -1514,12 +1515,7 @@ friend class CNode;
15141515
std::atomic<bool> wakeupSelectNeeded{false};
15151516

15161517
SocketEventsMode socketEventsMode;
1517-
#ifdef USE_KQUEUE
1518-
int kqueuefd{-1};
1519-
#endif
1520-
#ifdef USE_EPOLL
1521-
int epollfd{-1};
1522-
#endif
1518+
std::unique_ptr<EdgeTriggeredEvents> m_edge_trig_events{nullptr};
15231519

15241520
Mutex cs_sendable_receivable_nodes;
15251521
std::unordered_map<NodeId, CNode*> mapReceivableNodes GUARDED_BY(cs_sendable_receivable_nodes);

src/util/edge.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright (c) 2020-2024 The Dash Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <util/edge.h>
6+
7+
#include <logging.h>
8+
#include <util/sock.h>
9+
10+
#include <assert.h>
11+
12+
#ifdef USE_EPOLL
13+
#include <sys/epoll.h>
14+
#endif
15+
16+
#ifdef USE_KQUEUE
17+
#include <sys/event.h>
18+
#endif
19+
20+
EdgeTriggeredEvents::EdgeTriggeredEvents(SocketEventsMode events_mode)
21+
: m_mode(events_mode)
22+
{
23+
if (m_mode == SocketEventsMode::EPoll) {
24+
#ifdef USE_EPOLL
25+
m_fd = epoll_create1(0);
26+
if (m_fd == -1) {
27+
LogPrintf("Unable to initialize EdgeTriggeredEvents, epoll_create1 returned -1\n");
28+
return;
29+
}
30+
#else
31+
LogPrintf("Attempting to initialize EdgeTriggeredEvents for epoll without support compiled in!\n");
32+
return;
33+
#endif /* USE_EPOLL */
34+
} else if (m_mode == SocketEventsMode::KQueue) {
35+
#ifdef USE_KQUEUE
36+
m_fd = kqueue();
37+
if (m_fd == -1) {
38+
LogPrintf("Unable to initialize EdgeTriggeredEvents, kqueue returned -1\n");
39+
return;
40+
}
41+
#else
42+
LogPrintf("Attempting to initialize EdgeTriggeredEvents for kqueue without support compiled in!\n");
43+
return;
44+
#endif /* USE_KQUEUE */
45+
} else {
46+
assert(false);
47+
}
48+
m_valid = true;
49+
}
50+
51+
EdgeTriggeredEvents::~EdgeTriggeredEvents()
52+
{
53+
if (m_valid) {
54+
#if defined(USE_KQUEUE) || defined(USE_EPOLL)
55+
close(m_fd);
56+
#else
57+
assert(false);
58+
#endif /* defined(USE_KQUEUE) || defined(USE_EPOLL) */
59+
}
60+
}

src/util/edge.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright (c) 2020-2024 The Dash Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef BITCOIN_UTIL_EDGE_H
6+
#define BITCOIN_UTIL_EDGE_H
7+
8+
#include <cstdint>
9+
10+
enum class SocketEventsMode : int8_t;
11+
12+
/**
13+
* A manager for abstracting logic surrounding edge-triggered socket events
14+
* modes like kqueue and epoll.
15+
*/
16+
class EdgeTriggeredEvents
17+
{
18+
public:
19+
explicit EdgeTriggeredEvents(SocketEventsMode events_mode);
20+
~EdgeTriggeredEvents();
21+
22+
bool IsValid() const { return m_valid; }
23+
24+
public:
25+
/* File descriptor used to interact with events mode */
26+
int m_fd{-1};
27+
28+
private:
29+
/* Instance validity flag set during construction */
30+
bool m_valid{false};
31+
/* Flag for storing selected socket events mode */
32+
SocketEventsMode m_mode;
33+
};
34+
35+
#endif /* BITCOIN_UTIL_EDGE_H */

0 commit comments

Comments
 (0)