From 7997515588a5f67a55ef59cbb80747098c943767 Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Tue, 27 Oct 2020 14:34:23 +0100 Subject: [PATCH] [core] Fixed wrong usage of m_RecvDataLock. m_RecvDataCond must be used with m_RecvLock instead of m_RecvDataLock. m_RecvDataLock is only used to sync releaseSynch() calls. --- srtcore/core.cpp | 11 ++++++----- srtcore/core.h | 6 +++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/srtcore/core.cpp b/srtcore/core.cpp index e17195fc6..274446e90 100644 --- a/srtcore/core.cpp +++ b/srtcore/core.cpp @@ -7188,7 +7188,7 @@ int64_t CUDT::recvfile(fstream &ofs, int64_t &offset, int64_t size, int block) throw CUDTException(MJ_NOTSUP, MN_INVALBUFFERAPI, 0); } - ScopedLock recvguard(m_RecvLock); + UniqueLock recvguard(m_RecvLock); // Well, actually as this works over a FILE (fstream), not just a stream, // the size can be measured anyway and predicted if setting the offset might @@ -7248,8 +7248,7 @@ int64_t CUDT::recvfile(fstream &ofs, int64_t &offset, int64_t size, int block) } { - UniqueLock gl (m_RecvDataLock); - CSync rcond (m_RecvDataCond, gl); + CSync rcond (m_RecvDataCond, recvguard); THREAD_PAUSED(); while (stillConnected() && !m_pRcvBuffer->isRcvDataReady()) @@ -7634,7 +7633,8 @@ void CUDT::releaseSynch() enterCS(m_SendLock); leaveCS(m_SendLock); - CSync::lock_signal(m_RecvDataCond, m_RecvDataLock); + // Awake tsbpd() and srt_recv*(..) threads for them to check m_bClosing. + CSync::lock_signal(m_RecvDataCond, m_RecvLock); CSync::lock_signal(m_RcvTsbPdCond, m_RecvLock); enterCS(m_RecvDataLock); @@ -7802,6 +7802,7 @@ void CUDT::sendCtrl(UDTMessageType pkttype, const int32_t* lparam, void* rparam, /* Newly acknowledged data, signal TsbPD thread */ UniqueLock rcvlock (m_RecvLock); CSync tscond (m_RcvTsbPdCond, rcvlock); + // m_bTsbPdAckWakeup is protected by m_RecvLock in the tsbpd() thread if (m_bTsbPdAckWakeup) tscond.signal_locked(rcvlock); } @@ -7810,7 +7811,7 @@ void CUDT::sendCtrl(UDTMessageType pkttype, const int32_t* lparam, void* rparam, if (m_bSynRecving) { // signal a waiting "recv" call if there is any data available - CSync::lock_signal(m_RecvDataCond, m_RecvDataLock); + CSync::lock_signal(m_RecvDataCond, m_RecvLock); } // acknowledge any waiting epolls to read s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, SRT_EPOLL_IN, true); diff --git a/srtcore/core.h b/srtcore/core.h index 803e5b953..2b280b5bb 100644 --- a/srtcore/core.h +++ b/srtcore/core.h @@ -985,7 +985,7 @@ class CUDT bool m_bGroupTsbPd; // TSBPD should be used for GROUP RECEIVER instead. srt::sync::CThread m_RcvTsbPdThread; // Rcv TsbPD Thread handle - srt::sync::Condition m_RcvTsbPdCond; // TSBPD signals if reading is ready + srt::sync::Condition m_RcvTsbPdCond; // TSBPD signals if reading is ready. Use together with m_RecvLock. bool m_bTsbPdAckWakeup; // Signal TsbPd thread on Ack sent CallbackHolder m_cbAcceptHook; @@ -1017,11 +1017,11 @@ class CUDT // Protects access to m_iSndCurrSeqNo, m_iSndLastAck srt::sync::Mutex m_RecvAckLock; // Protects the state changes while processing incomming ACK (SRT_EPOLL_OUT) - srt::sync::Condition m_RecvDataCond; // used to block "recv" when there is no data + srt::sync::Condition m_RecvDataCond; // used to block "srt_recv*" when there is no data. Use together with m_RecvLock srt::sync::Mutex m_RecvDataLock; // lock associated to m_RecvDataCond + srt::sync::Mutex m_RecvLock; // used to synchronize "srt_recv*" call, protects TSBPD drift updates (CRcvBuffer::isRcvDataReady()) srt::sync::Mutex m_SendLock; // used to synchronize "send" call - srt::sync::Mutex m_RecvLock; // used to synchronize "recv" call, protects TSBPD drift updates (CRcvBuffer::isRcvDataReady()) srt::sync::Mutex m_RcvLossLock; // Protects the receiver loss list (access: CRcvQueue::worker, CUDT::tsbpd) srt::sync::Mutex m_StatsLock; // used to synchronize access to trace statistics