Skip to content

Commit

Permalink
clientContextImpl: Cap the number and age of beacons
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
JJL772 committed Dec 19, 2023
1 parent f1268ad commit d44adc9
Showing 1 changed file with 44 additions and 0 deletions.
44 changes: 44 additions & 0 deletions src/remoteClient/clientContextImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <pv/bitSetUtil.h>
#include <pv/standardPVField.h>
#include <pv/reftrack.h>
#include <pv/sharedPtr.h>

#define epicsExportSharedSymbols
#include <pv/pvAccess.h>
Expand Down Expand Up @@ -49,6 +50,9 @@ using std::tr1::static_pointer_cast;
using namespace std;
using namespace epics::pvData;

static const float maxBeaconLifetime = 180.f * 2.f;
static const int maxTrackedBeacons = 20000;

namespace epics {
namespace pvAccess {

Expand Down Expand Up @@ -4338,6 +4342,36 @@ class InternalClientContextImpl :
m_channelSearchManager->newServerDetected();
}

/**
* Handles cleanup of old beacons.
*/
class BeaconCleanupCallback : public TimerCallback
{
public:
typedef std::tr1::shared_ptr<BeaconCleanupCallback> shared_pointer;

BeaconCleanupCallback(InternalClientContextImpl& impl, osiSockAddr addr) :
m_from(addr),
m_impl(impl)
{
}

virtual void callback() OVERRIDE
{
Lock guard(m_impl.m_beaconMapMutex);
m_impl.m_beaconHandlers.erase(m_from);
}

virtual void timerStopped() OVERRIDE
{
this->callback(); // Remove the beacon if the timer is closed.
}

private:
osiSockAddr m_from;
InternalClientContextImpl& m_impl;
};

/**
* Get (and if necessary create) beacon handler.
* @param protocol the protocol.
Expand All @@ -4351,8 +4385,18 @@ class InternalClientContextImpl :
BeaconHandler::shared_pointer handler;
if (it == m_beaconHandlers.end())
{
// If we're tracking too many beacons, we'll just ignore this one
if (m_beaconHandlers.size() >= maxTrackedBeacons)
{
char ipa[64];
sockAddrToDottedIP(&responseFrom->sa, ipa, sizeof(ipa));
LOG(logLevelDebug, "Tracked beacon limit reached (%d), ignoring %s\n", maxTrackedBeacons, ipa);
return BeaconHandler::shared_pointer();
}

// stores weak_ptr
handler.reset(new BeaconHandler(internal_from_this(), responseFrom));
m_timer->scheduleAfterDelay(BeaconCleanupCallback::shared_pointer(new BeaconCleanupCallback(*this, *responseFrom)), maxBeaconLifetime);
m_beaconHandlers[*responseFrom] = handler;
}
else
Expand Down

0 comments on commit d44adc9

Please sign in to comment.