Fix changing shared memory in multi-process setup (#3462)
This change fixes two bugs: 1. A dead-lock that occurs between osrm-datastore and libosrm when an old dataset is free during a data update. This happened because the mutexes where acquired in a different order. 2. A region is deleted eventhough it is still in use. This happens when libosrm gets overtaken by osrm-datastore, so the new dataset is in the same region the old one was.
This commit is contained in:
parent
37051e1583
commit
c4b3cdfd80
@ -38,29 +38,33 @@ class SharedMemoryDataFacade : public ContiguousInternalMemoryDataFacadeBase
|
|||||||
// used anymore. We crash hard here if something goes wrong (noexcept).
|
// used anymore. We crash hard here if something goes wrong (noexcept).
|
||||||
virtual ~SharedMemoryDataFacade() noexcept
|
virtual ~SharedMemoryDataFacade() noexcept
|
||||||
{
|
{
|
||||||
|
// Now check if this is still the newest dataset
|
||||||
|
boost::interprocess::sharable_lock<boost::interprocess::named_upgradable_mutex>
|
||||||
|
current_regions_lock(shared_barriers->current_regions_mutex,
|
||||||
|
boost::interprocess::defer_lock);
|
||||||
|
|
||||||
boost::interprocess::scoped_lock<boost::interprocess::named_sharable_mutex> exclusive_lock(
|
boost::interprocess::scoped_lock<boost::interprocess::named_sharable_mutex> exclusive_lock(
|
||||||
data_region == storage::DATA_1 ? shared_barriers->regions_1_mutex
|
data_region == storage::DATA_1 ? shared_barriers->regions_1_mutex
|
||||||
: shared_barriers->regions_2_mutex,
|
: shared_barriers->regions_2_mutex,
|
||||||
boost::interprocess::defer_lock);
|
boost::interprocess::defer_lock);
|
||||||
|
|
||||||
// if this returns false this is still in use
|
// if this returns false this is still in use
|
||||||
if (exclusive_lock.try_lock())
|
if (current_regions_lock.try_lock() && exclusive_lock.try_lock())
|
||||||
{
|
{
|
||||||
if (storage::SharedMemory::RegionExists(data_region))
|
if (storage::SharedMemory::RegionExists(data_region))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(storage::SharedMemory::RegionExists(layout_region));
|
BOOST_ASSERT(storage::SharedMemory::RegionExists(layout_region));
|
||||||
|
|
||||||
// Now check if this is still the newest dataset
|
|
||||||
const boost::interprocess::sharable_lock<boost::interprocess::named_upgradable_mutex>
|
|
||||||
lock(shared_barriers->current_regions_mutex);
|
|
||||||
|
|
||||||
auto shared_regions = storage::makeSharedMemory(storage::CURRENT_REGIONS);
|
auto shared_regions = storage::makeSharedMemory(storage::CURRENT_REGIONS);
|
||||||
const auto current_timestamp =
|
const auto current_timestamp =
|
||||||
static_cast<const storage::SharedDataTimestamp *>(shared_regions->Ptr());
|
static_cast<const storage::SharedDataTimestamp *>(shared_regions->Ptr());
|
||||||
|
|
||||||
if (current_timestamp->timestamp == shared_timestamp)
|
// check if the memory region referenced by this facade needs cleanup
|
||||||
|
if (current_timestamp->data == data_region)
|
||||||
{
|
{
|
||||||
util::Log(logDEBUG) << "Retaining data with shared timestamp " << shared_timestamp;
|
BOOST_ASSERT(current_timestamp->layout == layout_region);
|
||||||
|
util::Log(logDEBUG) << "Retaining data with shared timestamp "
|
||||||
|
<< shared_timestamp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user