Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[XrdCl] Fix potential stream timeout when a new request is sent to an idle stream #2043

Merged
merged 1 commit into from
Jun 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/XrdCl/XrdClSIDManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

#include "XrdCl/XrdClSIDManager.hh"

#include <algorithm>

namespace XrdCl
{
//----------------------------------------------------------------------------
Expand Down Expand Up @@ -48,6 +50,7 @@ namespace XrdCl
}

memcpy( sid, &allocSID, 2 );
pAllocTime[allocSID] = time(0);
return Status();
}

Expand All @@ -60,6 +63,7 @@ namespace XrdCl
uint16_t relSID = 0;
memcpy( &relSID, sid, 2 );
pFreeSIDs.push_back( relSID );
pAllocTime.erase( relSID );
}

//----------------------------------------------------------------------------
Expand All @@ -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;
} );
}

//----------------------------------------------------------------------------
Expand Down
6 changes: 6 additions & 0 deletions src/XrdCl/XrdClSIDManager.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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
//------------------------------------------------------------------------
Expand Down Expand Up @@ -113,6 +118,7 @@ namespace XrdCl
uint16_t GetNumberOfAllocatedSIDs() const;

private:
std::unordered_map<uint16_t, time_t> pAllocTime;
std::list<uint16_t> pFreeSIDs;
std::set<uint16_t> pTimeOutSIDs;
uint16_t pSIDCeiling;
Expand Down
12 changes: 7 additions & 5 deletions src/XrdCl/XrdClXRootDTransport.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down