Skip to content

Commit aa5b980

Browse files
committed
clientContextImpl: Cap the number and age of beacons
Each beacon has an associated mutex. If we don't cap the beacon count, IOCs running on resource limited platforms like RTEMS may eventually run out of resources and crash.
1 parent 581d100 commit aa5b980

File tree

3 files changed

+53
-2
lines changed

3 files changed

+53
-2
lines changed

src/remote/beaconHandler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ BeaconHandler::BeaconHandler(Context::shared_pointer const & context,
2323
_serverChangeCount(-1),
2424
_first(true)
2525
{
26-
26+
_createdAt.getCurrent();
2727
}
2828

2929
BeaconHandler::~BeaconHandler()

src/remote/pv/beaconHandler.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ class BeaconHandler
6161
epics::pvData::int16 sequentalID,
6262
epics::pvData::int16 changeCount,
6363
const epics::pvData::PVFieldPtr& data);
64+
65+
epics::pvData::TimeStamp getCreationTime() const { return _createdAt; }
66+
6467
private:
6568
/**
6669
* Context instance.
@@ -86,6 +89,8 @@ class BeaconHandler
8689
*/
8790
bool _first;
8891

92+
epics::pvData::TimeStamp _createdAt;
93+
8994
/**
9095
* Update beacon.
9196
* @param remoteTransportRevision encoded (major, minor) revision.

src/remoteClient/clientContextImpl.cpp

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3957,7 +3957,7 @@ class InternalClientContextImpl :
39573957
static size_t num_instances;
39583958

39593959
InternalClientContextImpl(const Configuration::shared_pointer& conf) :
3960-
m_addressList(""), m_autoAddressList(true), m_connectionTimeout(30.0f), m_beaconPeriod(15.0f),
3960+
m_addressList(""), m_autoAddressList(true), m_connectionTimeout(30.0f), m_beaconPeriod(15.0f), m_maxBeacons(10), m_maxBeaconLifetime(15),
39613961
m_broadcastPort(PVA_BROADCAST_PORT), m_receiveBufferSize(MAX_TCP_RECV),
39623962
m_lastCID(0x10203040),
39633963
m_lastIOID(0x80706050),
@@ -4021,6 +4021,8 @@ class InternalClientContextImpl :
40214021
out << "AUTO_ADDR_LIST : " << (m_autoAddressList ? "true" : "false") << std::endl;
40224022
out << "CONNECTION_TIMEOUT : " << m_connectionTimeout << std::endl;
40234023
out << "BEACON_PERIOD : " << m_beaconPeriod << std::endl;
4024+
out << "BEACON_MAX : " << m_maxBeacons << std::endl;
4025+
out << "BEACON_MAX_AGE : " << m_maxBeaconLifetime << std::endl;
40244026
out << "BROADCAST_PORT : " << m_broadcastPort << std::endl;;
40254027
out << "RCV_BUFFER_SIZE : " << m_receiveBufferSize << std::endl;
40264028
out << "STATE : ";
@@ -4115,6 +4117,8 @@ class InternalClientContextImpl :
41154117
m_beaconPeriod = m_configuration->getPropertyAsFloat("EPICS_PVA_BEACON_PERIOD", m_beaconPeriod);
41164118
m_broadcastPort = m_configuration->getPropertyAsInteger("EPICS_PVA_BROADCAST_PORT", m_broadcastPort);
41174119
m_receiveBufferSize = m_configuration->getPropertyAsInteger("EPICS_PVA_MAX_ARRAY_BYTES", m_receiveBufferSize);
4120+
m_maxBeacons = m_configuration->getPropertyAsInteger("EPICS_PVA_BEACON_MAX", m_maxBeacons);
4121+
m_maxBeaconLifetime = m_configuration->getPropertyAsFloat("EPICS_PVA_BEACON_LIFETIME", m_maxBeaconLifetime);
41184122
}
41194123

41204124
void internalInitialize() {
@@ -4351,6 +4355,38 @@ class InternalClientContextImpl :
43514355
BeaconHandler::shared_pointer handler;
43524356
if (it == m_beaconHandlers.end())
43534357
{
4358+
TimeStamp now;
4359+
now.getCurrent();
4360+
4361+
double oldestAge = -1;
4362+
AddressBeaconHandlerMap::iterator oldestBeacon = m_beaconHandlers.end();
4363+
4364+
/* Before creating a new beacon, cleanup any old ones */
4365+
for (AddressBeaconHandlerMap::iterator it = m_beaconHandlers.begin(); it != m_beaconHandlers.end();)
4366+
{
4367+
double age = TimeStamp::diff(now, it->second->getCreationTime());
4368+
if (age >= m_maxBeaconLifetime)
4369+
{
4370+
AddressBeaconHandlerMap::iterator toErase = it;
4371+
++it; /* Iterator to current is invalidated by erase, so do this before */
4372+
m_beaconHandlers.erase(toErase);
4373+
continue;
4374+
}
4375+
4376+
if (age > oldestAge)
4377+
{
4378+
oldestAge = age;
4379+
oldestBeacon = it;
4380+
}
4381+
++it;
4382+
}
4383+
4384+
/* None were removed, axe the oldest we found to make room */
4385+
if (m_beaconHandlers.size() >= m_maxBeacons && oldestBeacon != m_beaconHandlers.end())
4386+
{
4387+
m_beaconHandlers.erase(oldestBeacon);
4388+
}
4389+
43544390
// stores weak_ptr
43554391
handler.reset(new BeaconHandler(internal_from_this(), responseFrom));
43564392
m_beaconHandlers[*responseFrom] = handler;
@@ -4443,6 +4479,16 @@ class InternalClientContextImpl :
44434479
*/
44444480
float m_beaconPeriod;
44454481

4482+
/**
4483+
* Max beacons allowed.
4484+
*/
4485+
uint32_t m_maxBeacons;
4486+
4487+
/**
4488+
* Max beacon lifetime
4489+
*/
4490+
float m_maxBeaconLifetime;
4491+
44464492
/**
44474493
* Broadcast (beacon, search) port number to listen to.
44484494
*/

0 commit comments

Comments
 (0)