@@ -1210,6 +1210,18 @@ void CConnman::ThreadSocketHandler()
12101210 SOCKET hSocketMax = 0 ;
12111211 bool have_fds = false ;
12121212
1213+ #ifndef WIN32
1214+ // We add a pipe to the read set so that the select() call can be woken up from the outside
1215+ // This is done when data is available for sending and at the same time optimistic sending was disabled
1216+ // when pushing the data.
1217+ // This is currently only implemented for POSIX compliant systems. This means that Windows will fall back to
1218+ // timing out after 50ms and then trying to send. This is ok as we assume that heavy-load daemons are usually
1219+ // run on Linux and friends.
1220+ FD_SET (wakeupPipe[0 ], &fdsetRecv);
1221+ hSocketMax = std::max (hSocketMax, (SOCKET)wakeupPipe[0 ]);
1222+ have_fds = true ;
1223+ #endif
1224+
12131225 BOOST_FOREACH (const ListenSocket& hListenSocket, vhListenSocket) {
12141226 FD_SET (hListenSocket.socket , &fdsetRecv);
12151227 hSocketMax = std::max (hSocketMax, hListenSocket.socket );
@@ -1276,6 +1288,20 @@ void CConnman::ThreadSocketHandler()
12761288 return ;
12771289 }
12781290
1291+ #ifndef WIN32
1292+ // drain the wakeup pipe
1293+ if (FD_ISSET (wakeupPipe[0 ], &fdsetRecv)) {
1294+ LogPrint (" net" , " woke up select()\n " );
1295+ char buf[128 ];
1296+ while (true ) {
1297+ int r = read (wakeupPipe[0 ], buf, sizeof (buf));
1298+ if (r <= 0 ) {
1299+ break ;
1300+ }
1301+ }
1302+ }
1303+ #endif
1304+
12791305 //
12801306 // Accept new connections
12811307 //
@@ -1426,6 +1452,21 @@ void CConnman::WakeMessageHandler()
14261452 condMsgProc.notify_one ();
14271453}
14281454
1455+ void CConnman::WakeSelect ()
1456+ {
1457+ #ifndef WIN32
1458+ if (wakeupPipe[1 ] == -1 ) {
1459+ return ;
1460+ }
1461+
1462+ LogPrint (" net" , " waking up select()\n " );
1463+
1464+ char buf[1 ];
1465+ if (write (wakeupPipe[1 ], buf, 1 ) != 1 ) {
1466+ LogPrint (" net" , " write to wakeupPipe failed\n " );
1467+ }
1468+ #endif
1469+ }
14291470
14301471
14311472
@@ -2387,6 +2428,22 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c
23872428 fMsgProcWake = false ;
23882429 }
23892430
2431+ #ifndef WIN32
2432+ if (pipe (wakeupPipe) != 0 ) {
2433+ wakeupPipe[0 ] = wakeupPipe[1 ] = -1 ;
2434+ LogPrint (" net" , " pipe() for wakeupPipe failed\n " );
2435+ } else {
2436+ int fFlags = fcntl (wakeupPipe[0 ], F_GETFL, 0 );
2437+ if (fcntl (wakeupPipe[0 ], F_SETFL, fFlags | O_NONBLOCK) == -1 ) {
2438+ LogPrint (" net" , " fcntl for O_NONBLOCK on wakeupPipe failed\n " );
2439+ }
2440+ fFlags = fcntl (wakeupPipe[1 ], F_GETFL, 0 );
2441+ if (fcntl (wakeupPipe[1 ], F_SETFL, fFlags | O_NONBLOCK) == -1 ) {
2442+ LogPrint (" net" , " fcntl for O_NONBLOCK on wakeupPipe failed\n " );
2443+ }
2444+ }
2445+ #endif
2446+
23902447 // Send and receive from sockets, accept connections
23912448 threadSocketHandler = std::thread (&TraceThread<std::function<void ()> >, " net" , std::function<void ()>(std::bind (&CConnman::ThreadSocketHandler, this )));
23922449
@@ -2512,6 +2569,12 @@ void CConnman::Stop()
25122569 semAddnode = NULL ;
25132570 delete semMasternodeOutbound;
25142571 semMasternodeOutbound = NULL ;
2572+
2573+ #ifndef WIN32
2574+ if (wakeupPipe[0 ] != -1 ) close (wakeupPipe[0 ]);
2575+ if (wakeupPipe[1 ] != -1 ) close (wakeupPipe[1 ]);
2576+ wakeupPipe[0 ] = wakeupPipe[1 ] = -1 ;
2577+ #endif
25152578}
25162579
25172580void CConnman::DeleteNode (CNode* pnode)
@@ -3054,7 +3117,7 @@ bool CConnman::NodeFullyConnected(const CNode* pnode)
30543117 return pnode && pnode->fSuccessfullyConnected && !pnode->fDisconnect ;
30553118}
30563119
3057- void CConnman::PushMessage (CNode* pnode, CSerializedNetMsg&& msg)
3120+ void CConnman::PushMessage (CNode* pnode, CSerializedNetMsg&& msg, bool allowOptimisticSend )
30583121{
30593122 size_t nMessageSize = msg.data .size ();
30603123 size_t nTotalSize = nMessageSize + CMessageHeader::HEADER_SIZE;
@@ -3071,7 +3134,7 @@ void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg)
30713134 size_t nBytesSent = 0 ;
30723135 {
30733136 LOCK (pnode->cs_vSend );
3074- bool optimisticSend (pnode->vSendMsg .empty ());
3137+ bool optimisticSend (allowOptimisticSend && pnode->vSendMsg .empty ());
30753138
30763139 // log total amount of bytes per command
30773140 pnode->mapSendBytesPerMsgCmd [msg.command ] += nTotalSize;
0 commit comments