我有两个进程使用boost共享内存,运行在一个循环中。
在每次迭代中,流程在共享内存中执行某些操作之前调用check_sanity(),我有一个场景,其中一个进程因对齐问题而崩溃:
/usr/local/include/boost/interprocess/mem_algo/detail/mem_algo_common.hpp:106: static void boost::interprocess::ipcdetail::memory_algorithm_common<MemoryAlgorithm>::assert_alignment(boost::interprocess::ipcdetail::memory_algorithm_common<MemoryAlgorithm>::size_type) [with MemoryAlgorithm = boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>; boost::interprocess::ipcdetail::memory_algorithm_common<MemoryAlgorithm>::size_type = long unsigned int]: Assertion `uint_ptr % Alignment == 0' failed.
./start.sh: line 20: 3034 Aborted (core dumped)崩溃后,第二个进程卡在check_sanity()函数中,当第一个进程重新启动时,他也会停留在那里。
我看了一下boost源代码,我发现check_sanity()函数中有一个check_sanity(),那里有一个assert,所以我猜想,assert中的第一个进程崩溃而没有解锁scoped mutex。
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
check_sanity()
{
//-----------------------
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
//-----------------------
imultiset_iterator ib(m_header.m_imultiset.begin()), ie(m_header.m_imultiset.end());
size_type free_memory = 0;
//Iterate through all blocks obtaining their size
for(; ib != ie; ++ib){
free_memory += (size_type)ib->m_size*Alignment;
algo_impl_t::assert_alignment(&*ib);
if(!algo_impl_t::check_alignment(&*ib))
return false;
}
//Check allocated bytes are less than size
if(m_header.m_allocated > m_header.m_size){
return false;
}
size_type block1_off =
priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes);
//Check free bytes are less than size
if(free_memory > (m_header.m_size - block1_off)){
return false;
}
return true;
}现在,当这种情况发生时,我的解决方案是删除共享内存并重新启动这两个进程,以便第一个进程将创建一个新的有效共享内存。
##Edit
我使用的是Boost版本1.74。
一个过程是读者,另一个过程是作者:
typedef boost::circular_buffer<SharedPtr, ShmemAllocator> Container;
bip::managed_shared_memory segment;
Container* createContainer(bip::managed_shared_memory &segment) {
bip::named_mutex container_lock{bip::open_or_create, SHM_MUTEX};
if (std::unique_lock open_lk{container_lock, std::try_to_lock}) {
segment = bip::managed_shared_memory(bip::open_or_create, SHM_NAME, SHM_SIZE);
return segment.find_or_construct<Container>(CONTAINER)(CONTAINER_SIZE, segment.get_segment_manager());
} else {
throw boost::interprocess::interprocess_exception("cannot lock for creating container shared memory");
}
}
Container* OpenContainer(bip::managed_shared_memory &segment) {
bip::named_mutex container_lock{bip::open_only, SHM_MUTEX};
if (std::unique_lock open_lk{container_lock, std::try_to_lock}) {
segment = bip::managed_shared_memory(bip::open_only, SHM_NAME);
auto container = segment.find<Container>(CONTAINER);
return container.first;
} else {
throw boost::interprocess::interprocess_exception("cannot lock for creating container shared memory");
}
}场景是,进程在循环中运行、停止、重新启动和使用现有的共享内存,在几次运行后偶尔会出现对齐问题,进程会被卡住。
我有两个问题:
scoped mutex以避免阻塞的进程?发布于 2022-06-13 11:27:13
崩溃后,第二个进程卡在check_sanity()函数中,在第一个进程重新启动后,他也停留在那里。
这部分是经过设计的。Boost Interprocess没有健壮互斥的便携实现(这是一个困难的问题)。
草图中的工作很常见,或者您可以在软件中使用定时的尝试锁来检测共享资源何时卡住了。
还请参阅此现象的许多其他示例:https://stackoverflow.com/search?tab=newest&q=user%3a85371%20robust%20interprocess
https://stackoverflow.com/questions/72596288
复制相似问题