From 5ddf53936258aab16ad8a345c1c5673e1e50edb9 Mon Sep 17 00:00:00 2001 From: David Smith Date: Fri, 16 Jun 2023 15:43:00 +0200 Subject: [PATCH] [XrdCl] Fix potential stream timeout when a new request is sent to an idle stream --- src/XrdCl/XrdClSIDManager.cc | 18 ++++++++++++++++++ src/XrdCl/XrdClSIDManager.hh | 6 ++++++ src/XrdCl/XrdClXRootDTransport.cc | 12 +++++++----- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/XrdCl/XrdClSIDManager.cc b/src/XrdCl/XrdClSIDManager.cc index 2a40c935067..8718d0eabac 100644 --- a/src/XrdCl/XrdClSIDManager.cc +++ b/src/XrdCl/XrdClSIDManager.cc @@ -18,6 +18,8 @@ #include "XrdCl/XrdClSIDManager.hh" +#include + namespace XrdCl { //---------------------------------------------------------------------------- @@ -48,6 +50,7 @@ namespace XrdCl } memcpy( sid, &allocSID, 2 ); + pAllocTime[allocSID] = time(0); return Status(); } @@ -60,6 +63,7 @@ namespace XrdCl uint16_t relSID = 0; memcpy( &relSID, sid, 2 ); pFreeSIDs.push_back( relSID ); + pAllocTime.erase( relSID ); } //---------------------------------------------------------------------------- @@ -71,6 +75,20 @@ namespace XrdCl uint16_t tiSID = 0; memcpy( &tiSID, sid, 2 ); pTimeOutSIDs.insert( tiSID ); + pAllocTime.erase( tiSID ); + } + + //---------------------------------------------------------------------------- + // Check if any SID was allocated at or before a given time + //---------------------------------------------------------------------------- + bool SIDManager::IsAnySIDOldAs( const time_t tlim ) const + { + XrdSysMutexHelper scopedLock( pMutex ); + return std::any_of( pAllocTime.begin(), pAllocTime.end(), + [tlim](const auto& p) + { + return p.second <= tlim; + } ); } //---------------------------------------------------------------------------- diff --git a/src/XrdCl/XrdClSIDManager.hh b/src/XrdCl/XrdClSIDManager.hh index 0fcdb11f5ce..0eccf4b7098 100644 --- a/src/XrdCl/XrdClSIDManager.hh +++ b/src/XrdCl/XrdClSIDManager.hh @@ -83,6 +83,11 @@ namespace XrdCl //------------------------------------------------------------------------ void TimeOutSID( uint8_t sid[2] ); + //---------------------------------------------------------------------------- + //! Check if any SID was allocated at or before a given time + //---------------------------------------------------------------------------- + bool IsAnySIDOldAs( const time_t tlim ) const; + //------------------------------------------------------------------------ //! Check if a SID is timed out //------------------------------------------------------------------------ @@ -113,6 +118,7 @@ namespace XrdCl uint16_t GetNumberOfAllocatedSIDs() const; private: + std::unordered_map pAllocTime; std::list pFreeSIDs; std::set pTimeOutSIDs; uint16_t pSIDCeiling; diff --git a/src/XrdCl/XrdClXRootDTransport.cc b/src/XrdCl/XrdClXRootDTransport.cc index 2fcaeb923db..0caad99a00f 100644 --- a/src/XrdCl/XrdClXRootDTransport.cc +++ b/src/XrdCl/XrdClXRootDTransport.cc @@ -795,20 +795,22 @@ namespace XrdCl XrdSysMutexHelper scopedLock( info->mutex ); - uint16_t allocatedSIDs = info->sidManager->GetNumberOfAllocatedSIDs(); + const time_t now = time(0); + const bool anySID = + info->sidManager->IsAnySIDOldAs( now - streamTimeout ); log->Dump( XRootDTransportMsg, "[%s] Stream inactive since %d seconds, " - "stream timeout: %d, allocated SIDs: %d, wait barrier: %s", + "stream timeout: %d, any SID: %d, wait barrier: %s", info->streamName.c_str(), inactiveTime, streamTimeout, - allocatedSIDs, Utils::TimeToString(info->waitBarrier).c_str() ); + anySID, Utils::TimeToString(info->waitBarrier).c_str() ); if( inactiveTime < streamTimeout ) return Status(); - if( time(0) < info->waitBarrier ) + if( now < info->waitBarrier ) return Status(); - if( !allocatedSIDs ) + if( !anySID ) return Status(); return Status( stError, errSocketTimeout );