@@ -1282,7 +1282,7 @@ bool CConnman::InactivityCheck(const CNode& node) const
12821282bool CConnman::GenerateSelectSet (const std::vector<CNode*>& nodes, Sockets& sockets)
12831283{
12841284 for (const ListenSocket& hListenSocket : vhListenSocket) {
1285- sockets.recv .insert (hListenSocket.sock -> Get ());
1285+ sockets.recv .insert (hListenSocket.sock . get ());
12861286 }
12871287
12881288 for (CNode* pnode : nodes) {
@@ -1309,13 +1309,13 @@ bool CConnman::GenerateSelectSet(const std::vector<CNode*>& nodes, Sockets& sock
13091309 continue ;
13101310 }
13111311
1312- sockets.err .insert (pnode->m_sock -> Get ());
1312+ sockets.err .insert (pnode->m_sock . get ());
13131313 if (select_send) {
1314- sockets.send .insert (pnode->m_sock -> Get ());
1314+ sockets.send .insert (pnode->m_sock . get ());
13151315 continue ;
13161316 }
13171317 if (select_recv) {
1318- sockets.recv .insert (pnode->m_sock -> Get ());
1318+ sockets.recv .insert (pnode->m_sock . get ());
13191319 }
13201320 }
13211321
@@ -1331,42 +1331,52 @@ void CConnman::SocketEvents(const std::vector<CNode*>& nodes, Sockets& sockets)
13311331 return ;
13321332 }
13331333
1334- std::unordered_map<SOCKET, struct pollfd > pollfds;
1335- for (SOCKET socket_id : sockets_to_check.recv ) {
1336- pollfds[socket_id].fd = socket_id;
1337- pollfds[socket_id].events |= POLLIN;
1338- }
1334+ // The same socket may be queued for more than one event (e.g. waiting for both recv
1335+ // and send - in both `sockets_to_check.recv` and `sockets_to_check.send`). We unique
1336+ // them into `by_socket`.
1337+ struct SockAndPollFd {
1338+ Sock* sock;
1339+ pollfd pfd;
1340+ };
1341+ std::unordered_map<SOCKET, SockAndPollFd> by_socket;
13391342
1340- for (SOCKET socket_id : sockets_to_check.send ) {
1341- pollfds[socket_id].fd = socket_id;
1342- pollfds[socket_id].events |= POLLOUT;
1343- }
1343+ // Add the sockets from `from` to `by_socket` for the given events.
1344+ auto AddSocketsForEvents = [&by_socket](auto & from, short events) {
1345+ for (Sock* sock : from) {
1346+ const SOCKET fd = sock->Get ();
1347+ by_socket[fd].sock = sock;
1348+ by_socket[fd].pfd .fd = fd;
1349+ by_socket[fd].pfd .events |= events;
1350+ }
1351+ };
13441352
1345- for (SOCKET socket_id : sockets_to_check.err ) {
1346- pollfds[socket_id].fd = socket_id;
1347- // These flags are ignored, but we set them for clarity
1348- pollfds[socket_id].events |= POLLERR|POLLHUP;
1349- }
1353+ AddSocketsForEvents (sockets_to_check.recv , POLLIN);
1354+ AddSocketsForEvents (sockets_to_check.send , POLLOUT);
1355+ // These flags are ignored by poll(2), but we set them for clarity.
1356+ AddSocketsForEvents (sockets_to_check.err , POLLERR | POLLHUP);
13501357
13511358 std::vector<struct pollfd > vpollfds;
1352- vpollfds.reserve (pollfds .size ());
1353- for (auto it : pollfds ) {
1354- vpollfds.push_back (std::move (it. second ) );
1359+ vpollfds.reserve (by_socket .size ());
1360+ for (auto & [socket, sock_and_pollfd] : by_socket ) {
1361+ vpollfds.push_back (sock_and_pollfd. pfd );
13551362 }
13561363
13571364 if (poll (vpollfds.data (), vpollfds.size (), SELECT_TIMEOUT_MILLISECONDS) < 0 ) return ;
13581365
13591366 if (interruptNet) return ;
13601367
13611368 for (struct pollfd pollfd_entry : vpollfds) {
1369+ auto pos = by_socket.find (pollfd_entry.fd );
1370+ assert (pos != by_socket.end ());
1371+ Sock* sock = pos->second .sock ;
13621372 if (pollfd_entry.revents & POLLIN) {
1363- sockets.recv .insert (pollfd_entry. fd );
1373+ sockets.recv .insert (sock );
13641374 }
13651375 if (pollfd_entry.revents & POLLOUT) {
1366- sockets.send .insert (pollfd_entry. fd );
1376+ sockets.send .insert (sock );
13671377 }
13681378 if (pollfd_entry.revents & (POLLERR|POLLHUP)) {
1369- sockets.err .insert (pollfd_entry. fd );
1379+ sockets.err .insert (sock );
13701380 }
13711381 }
13721382}
@@ -1394,20 +1404,18 @@ void CConnman::SocketEvents(const std::vector<CNode*>& nodes, Sockets& sockets)
13941404 FD_ZERO (&fdsetError);
13951405 SOCKET hSocketMax = 0 ;
13961406
1397- for (SOCKET hSocket : sockets_to_check.recv ) {
1398- FD_SET (hSocket, &fdsetRecv);
1399- hSocketMax = std::max (hSocketMax, hSocket);
1400- }
1401-
1402- for (SOCKET hSocket : sockets_to_check.send ) {
1403- FD_SET (hSocket, &fdsetSend);
1404- hSocketMax = std::max (hSocketMax, hSocket);
1405- }
1407+ // Add the sockets from `from` to the given fd set.
1408+ auto AddSocketsForEvents = [&hSocketMax](auto & from, fd_set& set) {
1409+ for (Sock* sock : from) {
1410+ const SOCKET fd = sock->Get ();
1411+ FD_SET (fd, &set);
1412+ hSocketMax = std::max (hSocketMax, fd);
1413+ }
1414+ };
14061415
1407- for (SOCKET hSocket : sockets_to_check.err ) {
1408- FD_SET (hSocket, &fdsetError);
1409- hSocketMax = std::max (hSocketMax, hSocket);
1410- }
1416+ AddSocketsForEvents (sockets_to_check.recv , fdsetRecv);
1417+ AddSocketsForEvents (sockets_to_check.send , fdsetSend);
1418+ AddSocketsForEvents (sockets_to_check.err , fdsetError);
14111419
14121420 int nSelect = select (hSocketMax + 1 , &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
14131421
@@ -1426,21 +1434,21 @@ void CConnman::SocketEvents(const std::vector<CNode*>& nodes, Sockets& sockets)
14261434 return ;
14271435 }
14281436
1429- for (SOCKET hSocket : sockets_to_check.recv ) {
1430- if (FD_ISSET (hSocket , &fdsetRecv)) {
1431- sockets.recv .insert (hSocket );
1437+ for (Sock* sock : sockets_to_check.recv ) {
1438+ if (FD_ISSET (sock-> Get () , &fdsetRecv)) {
1439+ sockets.recv .insert (sock );
14321440 }
14331441 }
14341442
1435- for (SOCKET hSocket : sockets_to_check.send ) {
1436- if (FD_ISSET (hSocket , &fdsetSend)) {
1437- sockets.send .insert (hSocket );
1443+ for (Sock* sock : sockets_to_check.send ) {
1444+ if (FD_ISSET (sock-> Get () , &fdsetSend)) {
1445+ sockets.send .insert (sock );
14381446 }
14391447 }
14401448
1441- for (SOCKET hSocket : sockets_to_check.err ) {
1442- if (FD_ISSET (hSocket , &fdsetError)) {
1443- sockets.err .insert (hSocket );
1449+ for (Sock* sock : sockets_to_check.err ) {
1450+ if (FD_ISSET (sock-> Get () , &fdsetError)) {
1451+ sockets.err .insert (sock );
14441452 }
14451453 }
14461454}
@@ -1460,8 +1468,7 @@ void CConnman::SocketHandler()
14601468 //
14611469 for (const ListenSocket& hListenSocket : vhListenSocket)
14621470 {
1463- if (hListenSocket.sock ->IsValid () && sockets.recv .count (hListenSocket.sock ->Get ()) > 0 )
1464- {
1471+ if (hListenSocket.sock ->IsValid () && sockets.recv .count (hListenSocket.sock .get ()) > 0 ) {
14651472 AcceptConnection (hListenSocket);
14661473 }
14671474 }
@@ -1484,9 +1491,9 @@ void CConnman::SocketHandler()
14841491 if (!pnode->m_sock ->IsValid ()) {
14851492 continue ;
14861493 }
1487- recvSet = sockets.recv .count (pnode->m_sock -> Get ()) > 0 ;
1488- sendSet = sockets.send .count (pnode->m_sock -> Get ()) > 0 ;
1489- errorSet = sockets.err .count (pnode->m_sock -> Get ()) > 0 ;
1494+ recvSet = sockets.recv .count (pnode->m_sock . get ()) > 0 ;
1495+ sendSet = sockets.send .count (pnode->m_sock . get ()) > 0 ;
1496+ errorSet = sockets.err .count (pnode->m_sock . get ()) > 0 ;
14901497 }
14911498 if (recvSet || errorSet)
14921499 {
0 commit comments