Shm: throw on bad_alloc, option to disable

This commit is contained in:
Alexey Rybalchenko
2020-05-17 14:46:15 +02:00
parent 2916a491b9
commit 0d03c76a75
7 changed files with 42 additions and 29 deletions

View File

@@ -52,7 +52,7 @@ struct SharedMemoryError : std::runtime_error { using std::runtime_error::runtim
class Manager
{
public:
Manager(std::string id, std::string deviceId, size_t size)
Manager(std::string id, std::string deviceId, size_t size, bool throwOnBadAlloc)
: fShmId(std::move(id))
, fDeviceId(std::move(deviceId))
, fSegmentName("fmq_" + fShmId + "_main")
@@ -69,6 +69,7 @@ class Manager
, fMsgCounter(0)
, fHeartbeatThread()
, fSendHeartbeats(true)
, fThrowOnBadAlloc(throwOnBadAlloc)
{
using namespace boost::interprocess;
LOG(debug) << "created/opened shared memory segment '" << "fmq_" << fShmId << "_main" << "' of " << size << " bytes. Available are " << fSegment.get_free_memory() << " bytes.";
@@ -415,6 +416,8 @@ class Manager
}
}
bool ThrowingOnBadAlloc() const { return fThrowOnBadAlloc; }
private:
std::string fShmId;
std::string fDeviceId;
@@ -440,6 +443,7 @@ class Manager
std::thread fHeartbeatThread;
std::atomic<bool> fSendHeartbeats;
bool fThrowOnBadAlloc;
};
} // namespace shmem

View File

@@ -12,7 +12,7 @@
#include "Manager.h"
#include "Region.h"
#include "UnmanagedRegion.h"
#include <fairmq/Tools.h>
#include <FairMQLogger.h>
#include <FairMQMessage.h>
#include <FairMQUnmanagedRegion.h>
@@ -37,7 +37,7 @@ class Message final : public fair::mq::Message
public:
Message(Manager& manager, FairMQTransportFactory* factory = nullptr)
: fair::mq::Message{factory}
: fair::mq::Message(factory)
, fManager(manager)
, fQueued(false)
, fMeta{0, 0, 0, -1}
@@ -48,7 +48,7 @@ class Message final : public fair::mq::Message
}
Message(Manager& manager, const size_t size, FairMQTransportFactory* factory = nullptr)
: fair::mq::Message{factory}
: fair::mq::Message(factory)
, fManager(manager)
, fQueued(false)
, fMeta{0, 0, 0, -1}
@@ -60,7 +60,7 @@ class Message final : public fair::mq::Message
}
Message(Manager& manager, void* data, const size_t size, fairmq_free_fn* ffn, void* hint = nullptr, FairMQTransportFactory* factory = nullptr)
: fair::mq::Message{factory}
: fair::mq::Message(factory)
, fManager(manager)
, fQueued(false)
, fMeta{0, 0, 0, -1}
@@ -79,7 +79,7 @@ class Message final : public fair::mq::Message
}
Message(Manager& manager, UnmanagedRegionPtr& region, void* data, const size_t size, void* hint = 0, FairMQTransportFactory* factory = nullptr)
: fair::mq::Message{factory}
: fair::mq::Message(factory)
, fManager(manager)
, fQueued(false)
, fMeta{size, static_cast<UnmanagedRegion*>(region.get())->fRegionId, reinterpret_cast<size_t>(hint), -1}
@@ -97,7 +97,7 @@ class Message final : public fair::mq::Message
}
Message(Manager& manager, MetaHeader& hdr, FairMQTransportFactory* factory = nullptr)
: fair::mq::Message{factory}
: fair::mq::Message(factory)
, fManager(manager)
, fQueued(false)
, fMeta{hdr}
@@ -221,6 +221,8 @@ class Message final : public fair::mq::Message
bool InitializeChunk(const size_t size)
{
tools::RateLimiter rateLimiter(20);
while (fMeta.fHandle < 0) {
try {
boost::interprocess::managed_shared_memory::size_type actualSize = size;
@@ -228,7 +230,10 @@ class Message final : public fair::mq::Message
fLocalPtr = fManager.Segment().allocation_command<char>(boost::interprocess::allocate_new, size, actualSize, hint);
} catch (boost::interprocess::bad_alloc& ba) {
// LOG(warn) << "Shared memory full...";
std::this_thread::sleep_for(std::chrono::milliseconds(50));
if (fManager.ThrowingOnBadAlloc()) {
throw MessageBadAlloc(tools::ToString("shmem: could not create a message of size ", size));
}
rateLimiter.maybe_sleep();
if (fManager.Interrupted()) {
return false;
} else {

View File

@@ -59,11 +59,13 @@ class TransportFactory final : public fair::mq::TransportFactory
std::string sessionName = "default";
size_t segmentSize = 2000000000;
bool autolaunchMonitor = false;
bool throwOnBadAlloc = true;
if (config) {
numIoThreads = config->GetProperty<int>("io-threads", numIoThreads);
sessionName = config->GetProperty<std::string>("session", sessionName);
segmentSize = config->GetProperty<size_t>("shm-segment-size", segmentSize);
autolaunchMonitor = config->GetProperty<bool>("shm-monitor", autolaunchMonitor);
throwOnBadAlloc = config->GetProperty<bool>("shm-throw-bad-alloc", throwOnBadAlloc);
} else {
LOG(debug) << "ProgOptions not available! Using defaults.";
}
@@ -84,8 +86,7 @@ class TransportFactory final : public fair::mq::TransportFactory
Manager::StartMonitor(fShmId);
}
fManager = tools::make_unique<Manager>(fShmId, fDeviceId, segmentSize);
fManager = tools::make_unique<Manager>(fShmId, fDeviceId, segmentSize, throwOnBadAlloc);
} catch (boost::interprocess::interprocess_exception& e) {
LOG(error) << "Could not initialize shared memory transport: " << e.what();
throw std::runtime_error(tools::ToString("Could not initialize shared memory transport: ", e.what()));