Skip to content

Commit d44adc9

Browse files
committed
clientContextImpl: Cap the number and age of beacons
Each beacon has an associated mutex. If we allocate too many beacons on resource constrained systems, i.e. RTEMS, we may run out of resources and crash.
1 parent f1268ad commit d44adc9

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

src/remoteClient/clientContextImpl.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <pv/bitSetUtil.h>
2121
#include <pv/standardPVField.h>
2222
#include <pv/reftrack.h>
23+
#include <pv/sharedPtr.h>
2324

2425
#define epicsExportSharedSymbols
2526
#include <pv/pvAccess.h>
@@ -49,6 +50,9 @@ using std::tr1::static_pointer_cast;
4950
using namespace std;
5051
using namespace epics::pvData;
5152

53+
static const float maxBeaconLifetime = 180.f * 2.f;
54+
static const int maxTrackedBeacons = 20000;
55+
5256
namespace epics {
5357
namespace pvAccess {
5458

@@ -4338,6 +4342,36 @@ class InternalClientContextImpl :
43384342
m_channelSearchManager->newServerDetected();
43394343
}
43404344

4345+
/**
4346+
* Handles cleanup of old beacons.
4347+
*/
4348+
class BeaconCleanupCallback : public TimerCallback
4349+
{
4350+
public:
4351+
typedef std::tr1::shared_ptr<BeaconCleanupCallback> shared_pointer;
4352+
4353+
BeaconCleanupCallback(InternalClientContextImpl& impl, osiSockAddr addr) :
4354+
m_from(addr),
4355+
m_impl(impl)
4356+
{
4357+
}
4358+
4359+
virtual void callback() OVERRIDE
4360+
{
4361+
Lock guard(m_impl.m_beaconMapMutex);
4362+
m_impl.m_beaconHandlers.erase(m_from);
4363+
}
4364+
4365+
virtual void timerStopped() OVERRIDE
4366+
{
4367+
this->callback(); // Remove the beacon if the timer is closed.
4368+
}
4369+
4370+
private:
4371+
osiSockAddr m_from;
4372+
InternalClientContextImpl& m_impl;
4373+
};
4374+
43414375
/**
43424376
* Get (and if necessary create) beacon handler.
43434377
* @param protocol the protocol.
@@ -4351,8 +4385,18 @@ class InternalClientContextImpl :
43514385
BeaconHandler::shared_pointer handler;
43524386
if (it == m_beaconHandlers.end())
43534387
{
4388+
// If we're tracking too many beacons, we'll just ignore this one
4389+
if (m_beaconHandlers.size() >= maxTrackedBeacons)
4390+
{
4391+
char ipa[64];
4392+
sockAddrToDottedIP(&responseFrom->sa, ipa, sizeof(ipa));
4393+
LOG(logLevelDebug, "Tracked beacon limit reached (%d), ignoring %s\n", maxTrackedBeacons, ipa);
4394+
return BeaconHandler::shared_pointer();
4395+
}
4396+
43544397
// stores weak_ptr
43554398
handler.reset(new BeaconHandler(internal_from_this(), responseFrom));
4399+
m_timer->scheduleAfterDelay(BeaconCleanupCallback::shared_pointer(new BeaconCleanupCallback(*this, *responseFrom)), maxBeaconLifetime);
43564400
m_beaconHandlers[*responseFrom] = handler;
43574401
}
43584402
else

0 commit comments

Comments
 (0)