From e86b2203b8b036f4abf40b9683dea04ee95a9a7d Mon Sep 17 00:00:00 2001 From: chengang06 Date: Fri, 5 Mar 2021 11:11:10 +0800 Subject: [PATCH 1/2] fix epoll event loss problem --- srtcore/core.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/srtcore/core.cpp b/srtcore/core.cpp index 2d5cb2d86..02f796fb1 100644 --- a/srtcore/core.cpp +++ b/srtcore/core.cpp @@ -7553,7 +7553,19 @@ int CUDT::sendCtrlAck(CPacket& ctrlpkt, int size) CSync::lock_signal(m_RecvDataCond, m_RecvLock); } // acknowledge any waiting epolls to read + // fix SRT_EPOLL_IN event loss but rcvbuffer still have data: + // 1. user call receive/receivemessage(about line number:6482) + // 2. after read/receive, if rcvbuffer is empty, will set SRT_EPOLL_IN event to false + // 3. but if we do not do some lock work here, will cause some sync problems between threads: + // (1) user thread: call receive/receivemessage + // (2) user thread: read data + // (3) user thread: no data in rcvbuffer, set SRT_EPOLL_IN event to false + // (4) receive thread: receive data and set SRT_EPOLL_IN to true + // (5) user thread: set SRT_EPOLL_IN to false + // 4. so , m_RecvLock must be used here to protect epoll event + enterCS(m_RecvLock); s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, SRT_EPOLL_IN, true); + leaveCS(m_RecvLock); #if ENABLE_EXPERIMENTAL_BONDING if (m_parent->m_GroupOf) { From a3d0b6ed8193ef9143f7bf76455dca620f235a22 Mon Sep 17 00:00:00 2001 From: chengang06 Date: Tue, 9 Mar 2021 10:35:32 +0800 Subject: [PATCH 2/2] fix epoll event loss problem, use elegant lock method --- srtcore/core.cpp | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/srtcore/core.cpp b/srtcore/core.cpp index 87e34cbfd..c2d4caedf 100644 --- a/srtcore/core.cpp +++ b/srtcore/core.cpp @@ -7554,25 +7554,27 @@ int CUDT::sendCtrlAck(CPacket& ctrlpkt, int size) } else { - if (m_config.bSynRecving) - { - // signal a waiting "recv" call if there is any data available - CSync::lock_signal(m_RecvDataCond, m_RecvLock); - } - // acknowledge any waiting epolls to read - // fix SRT_EPOLL_IN event loss but rcvbuffer still have data: - // 1. user call receive/receivemessage(about line number:6482) - // 2. after read/receive, if rcvbuffer is empty, will set SRT_EPOLL_IN event to false - // 3. but if we do not do some lock work here, will cause some sync problems between threads: - // (1) user thread: call receive/receivemessage - // (2) user thread: read data - // (3) user thread: no data in rcvbuffer, set SRT_EPOLL_IN event to false - // (4) receive thread: receive data and set SRT_EPOLL_IN to true - // (5) user thread: set SRT_EPOLL_IN to false - // 4. so , m_RecvLock must be used here to protect epoll event - enterCS(m_RecvLock); - s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, SRT_EPOLL_IN, true); - leaveCS(m_RecvLock); + { + UniqueLock rdlock (m_RecvLock); + CSync rdcond (m_RecvDataCond, rdlock); + if (m_config.bSynRecving) + { + // signal a waiting "recv" call if there is any data available + rdcond.signal_locked(rdlock); + } + // acknowledge any waiting epolls to read + // fix SRT_EPOLL_IN event loss but rcvbuffer still have data: + // 1. user call receive/receivemessage(about line number:6482) + // 2. after read/receive, if rcvbuffer is empty, will set SRT_EPOLL_IN event to false + // 3. but if we do not do some lock work here, will cause some sync problems between threads: + // (1) user thread: call receive/receivemessage + // (2) user thread: read data + // (3) user thread: no data in rcvbuffer, set SRT_EPOLL_IN event to false + // (4) receive thread: receive data and set SRT_EPOLL_IN to true + // (5) user thread: set SRT_EPOLL_IN to false + // 4. so , m_RecvLock must be used here to protect epoll event + s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, SRT_EPOLL_IN, true); + } #if ENABLE_EXPERIMENTAL_BONDING if (m_parent->m_GroupOf) {