Boost进程间互斥锁崩溃,而不是等待锁
Boost interprocess mutex crashes instead of waiting on a lock?
我已经在这好几天了(甚至张贴在boost论坛上),能够使第二个进程识别锁定的互斥体似乎不起作用。请帮助。这是代码:
通用头文件:SharedObject.hpp
#ifndef SHAREDOBJECT_HPP
#define SHAREDOBJECT_HPP
#include <iostream>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/list.hpp>
#include <time.h>//for sleep
//--------for mutexes
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/sync/interprocess_upgradable_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/sharable_lock.hpp>
#include <boost/interprocess/sync/upgradable_lock.hpp>
#define MUTEX_SHARED_MEMORY_NAME "NavSharedMemoryMutex"
#define DATAOUTPUT "OutputFromObject"
#define INITIAL_MEM 650000
using namespace std;
namespace bip = boost::interprocess;
class SharedMutex
{
private:
typedef bip::interprocess_upgradable_mutex upgradable_mutex_type;
mutable upgradable_mutex_type mutex;
volatile int counter;
public:
void lockWithReadLock() const { bip::sharable_lock<upgradable_mutex_type> lock(mutex); }
void lockWithWriteLock() { bip::scoped_lock<upgradable_mutex_type> lock(mutex); }
};
//-------------------------------------- SharedMemoryObject
class SharedObject
{
public:
SharedMutex* sharedMutex;
};
typedef bip::allocator<SharedObject, bip::managed_shared_memory::segment_manager> ShmemAllocator;
typedef bip::list<SharedObject, ShmemAllocator> SharedMemData;
#endif /* SHAREDOBJECT_HPP */
这是第一个程序
#include "SharedObject.hpp"
int main()
{
//-----------Create shared memory and put shared object into it
bip::managed_shared_memory* seg;
SharedMemData *sharedMemOutputList;
bip::shared_memory_object::remove(DATAOUTPUT);
seg = new bip::managed_shared_memory(bip::create_only, DATAOUTPUT, INITIAL_MEM);
const ShmemAllocator alloc_inst(seg->get_segment_manager());
sharedMemOutputList = seg->construct<SharedMemData>("TrackOutput")(alloc_inst);
std::size_t beforeAllocation = seg->get_free_memory();
std::cout<<"nBefore allocation = "<< beforeAllocation <<"n";
SharedObject temp;
sharedMemOutputList->push_back(temp);
//-------------------Create a shared memory for holding a mutex
bip::shared_memory_object::remove(MUTEX_SHARED_MEMORY_NAME);//BUG: If another program also removes this, then there won't be any shared memory remaining. This problem has to be handled better. This is not the right way to deal with shared mutexes.
bip::shared_memory_object shm(bip::create_only, MUTEX_SHARED_MEMORY_NAME, bip::read_write);
shm.truncate(sizeof (SharedMutex)); //Allocate memory in shared memory for the mutex
bip::mapped_region region(shm, bip::read_write); // Map the whole shared memory into this process.
new (region.get_address()) SharedMutex; // Construct the SharedMutex using placement new
temp.sharedMutex = static_cast<SharedMutex *> (region.get_address()); //Store the mutex object address for future reference
{
std::cout<<"Program 1: Before first locking -------------------------- 1 vn";
temp.sharedMutex->lockWithWriteLock();
const unsigned int SLEEP_TIME_IN_SECOND = 60;
std::cout<<"Program 1: sleep for "<< SLEEP_TIME_IN_SECOND << "n";
sleep(SLEEP_TIME_IN_SECOND);
std::cout<<"Program 1: Finished sleepingn";
}
std::cout<<"Program 1: unlocked -------------------------------------- 1 ^n";
seg->destroy<SharedMemData>("TrackOutput");
delete seg;
return 0;
}//main
这是第二个程序:
#include "SharedObject.hpp"
#define CREATE_SEPARATE_MUTEX
int main()
{
bip::managed_shared_memory segment(bip::open_only, DATAOUTPUT); //Open the managed segment
SharedMemData* sharedMemoryTrackOutputList = segment.find<SharedMemData>("TrackOutput").first; //Find the list using the c-string name
assert(sharedMemoryTrackOutputList);
std::cout << "SharedMemoryData address found at = " << (void *) sharedMemoryTrackOutputList << "n";
std::cout << "size = " << sharedMemoryTrackOutputList->size() << "n";
SharedMemData::iterator iter = sharedMemoryTrackOutputList->begin();
#ifndef CREATE_SEPARATE_MUTEX
//-------------------Create a shared memory for holding a mutex
bip::shared_memory_object shm(bip::open_or_create, MUTEX_SHARED_MEMORY_NAME, bip::read_write);
shm.truncate(sizeof (SharedMutex)); //Allocate memory in shared memory for the mutex
bip::mapped_region region(shm, bip::read_write); // Map the whole shared memory into this process.
new (region.get_address()) SharedMutex; // Construct the SharedMutex using placement new
(*iter).sharedMutex = static_cast<SharedMutex *> (region.get_address()); //Store the mutex object address for future reference
#endif
{
std::cout<<"Program 2: Before first locking -------------------------- 1 vn";
(*iter).sharedMutex->lockWithWriteLock();
const unsigned int SLEEP_TIME_IN_SECOND = 1;
std::cout<<"Program 2: sleep for "<< SLEEP_TIME_IN_SECOND << "n";
sleep(SLEEP_TIME_IN_SECOND);
std::cout<<"Program 2: Finished sleepingn";
}
std::cout<<"Program 2: unlocked -------------------------------------- 1 ^n";
return 0;
}//main
程序1运行良好。
程序2给出如下输出:
SharedMemoryData address found at = 0x7f0a4c2b8118
size = 1
Program 2: Before first locking -------------------------- 1 v
terminate called after throwing an instance of 'boost::interprocess::lock_exception'
what(): boost::interprocess::lock_exception
Aborted (core dumped)
我先运行program1,它锁定互斥锁并使其锁定60秒。在此期间,我运行程序2,看看它是否等待锁,但它崩溃了。如何让程序2等待互斥锁直到程序1完成对共享内存的写入?
好吧,这是你的代码的一些问题。
-
SharedMutex
存储在另一个内存区域,在第二个程序中没有映射。 -
映射的区域可以有不同的基址,所以原始指针在这种环境下不起作用。使用
boost::interprocess::offset_ptr
代替。但是,请注意,这些工作指针指向相同的内存段,所以把你的SharedMutex和SharedObject放在同一个段(或者代替所有这些,使用named_mutex
)是有意义的。 -
在main1中,在修改成员变量
sharedMutex
之前,将temp
复制到共享内存。您应该确保在共享内存中您的指针(offset_ptr
)实际上是有效的。 -
当您尝试使用
lockWithWriteLock
函数锁定scoped_lock
时,锁在函数退出时立即解锁。因此,一旦您修复了上述所有问题并消除了崩溃,您仍然不会得到预期的输出-您的代码逻辑应该更改。
和代码:
sharedObject.hpp
#ifndef SHAREDOBJECT_HPP
#define SHAREDOBJECT_HPP
#include <iostream>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/list.hpp>
#include <time.h>//for sleep
//--------for mutexes
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/sync/interprocess_upgradable_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/sharable_lock.hpp>
#include <boost/interprocess/sync/upgradable_lock.hpp>
#define MUTEX_SHARED_MEMORY_NAME "NavSharedMemoryMutex"
#define DATAOUTPUT "OutputFromObject"
#define INITIAL_MEM 650000
using namespace std;
namespace bip = boost::interprocess;
class SharedMutex
{
public:
typedef bip::interprocess_upgradable_mutex upgradable_mutex_type;
mutable upgradable_mutex_type mutex;
};
//-------------------------------------- SharedMemoryObject
class SharedObject
{
public:
SharedMutex* sharedMutex;
};
typedef bip::allocator<SharedObject, bip::managed_shared_memory::segment_manager> ShmemAllocator;
typedef bip::list<SharedObject, ShmemAllocator> SharedMemData;
#endif /* SHAREDOBJECT_HPP */
Program1:
#include "SharedObject.hpp"
int main()
{
//-----------Create shared memory and put shared object into it
bip::managed_shared_memory* seg;
SharedMemData *sharedMemOutputList;
bip::shared_memory_object::remove(DATAOUTPUT);
seg = new bip::managed_shared_memory(bip::create_only, DATAOUTPUT, INITIAL_MEM);
const ShmemAllocator alloc_inst(seg->get_segment_manager());
sharedMemOutputList = seg->construct<SharedMemData>("TrackOutput")(alloc_inst);
SharedObject temp;
//-------------------Create a shared memory for holding a mutex
bip::shared_memory_object::remove(MUTEX_SHARED_MEMORY_NAME);//BUG: If another program also removes this, then there won't be any shared memory remaining. This problem has to be handled better. This is not the right way to deal with shared mutexes.
bip::shared_memory_object shm(bip::open_or_create, MUTEX_SHARED_MEMORY_NAME, bip::read_write);
shm.truncate(sizeof(SharedMutex)); //Allocate memory in shared memory for the mutex
bip::mapped_region region(shm, bip::read_write); // Map the whole shared memory into this process.
new (region.get_address()) SharedMutex; // Construct the SharedMutex using placement new
temp.sharedMutex = static_cast<SharedMutex *> (region.get_address()); //Store the mutex object address for future reference
std::cout << "Region address " << region.get_address() << "n";
sharedMemOutputList->push_back(temp);
//initiate scope for scoped mutex
{
std::cout << "Program 1: Going to do 1st locking -------------------------- 1 vn";
bip::scoped_lock<bip::interprocess_upgradable_mutex> lock(temp.sharedMutex->mutex);
const unsigned int SLEEP_TIME_IN_SECOND = 10;
std::cout<<"Program 1: locked. Now sleep for "<< SLEEP_TIME_IN_SECOND << "n";
sleep(SLEEP_TIME_IN_SECOND);
std::cout << "Program 1: Finished sleepingn";
}
std::cout << "Program 1: unlocked ----------------------------------------- 1 ^n";
//seg->destroy<SharedMemData>("TrackOutput");delete seg;
return 0;
}//main
and Program2:
#include "SharedObject.hpp"
#define READ_LOCK_TESTING
#ifndef READ_LOCK_TESTING
#define WRITE_LOCK_TESTING
#endif
int main()
{
bip::managed_shared_memory segment(bip::open_only, DATAOUTPUT); //Open the managed segment
SharedMemData* sharedMemoryTrackOutputList = segment.find<SharedMemData>("TrackOutput").first; //Find the list using the c-string name
assert(sharedMemoryTrackOutputList);
std::cout << "SharedMemoryData address found at = " << (void *)sharedMemoryTrackOutputList << "n";
std::cout << "size = " << sharedMemoryTrackOutputList->size() << "n";
SharedMemData::iterator iter = sharedMemoryTrackOutputList->begin();
bip::shared_memory_object shm(bip::open_or_create, MUTEX_SHARED_MEMORY_NAME, bip::read_write);
bip::mapped_region region(shm, bip::read_write); // Map the whole shared memory into this process.
std::cout << "Region address " << region.get_address() << "n";
//Initiate the scope for the scoped mutex
{
std::cout << "Program 2: Going to do 2nd locking -------------------------- 2 vn";
iter->sharedMutex = static_cast<SharedMutex*>(region.get_address());
#ifdef WRITE_LOCK_TESTING
bip::scoped_lock<bip::interprocess_upgradable_mutex> lock((*iter).sharedMutex->mutex);//write lock
#endif
#ifdef READ_LOCK_TESTING
bip::sharable_lock<bip::interprocess_upgradable_mutex> lock((*iter).sharedMutex->mutex);//read lock
#endif
const unsigned int SLEEP_TIME_IN_SECOND = 10;
std::cout << "Program 2: locked. Now sleep for " << SLEEP_TIME_IN_SECOND << "n";
sleep(SLEEP_TIME_IN_SECOND);
std::cout << "Program 2: Finished sleepingn";
}
std::cout << "Program 2: unlocked ------------------------------------------ 2 ^n";
return 0;
}//main
Rostislav建议使用命名互斥锁,所以我也举了一个命名互斥锁的例子(尽管我想要读/写锁,而那些锁似乎不支持命名互斥锁……我可能是错的)。
程序1:#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <fstream>
#include <iostream>
#include <cstdio>
int main ()
{
using namespace boost::interprocess;
try
{
struct mutex_remove
{
mutex_remove() { named_mutex::remove("fstream_named_mutex"); }
~mutex_remove(){ named_mutex::remove("fstream_named_mutex"); }
} remover;
//Open or create the named mutex
named_mutex mutex(open_or_create, "fstream_named_mutex");
{
std::cout<<"gonna lockn";
scoped_lock<named_mutex> lock(mutex);
const unsigned int SLEEP_TIME_IN_SECOND = 10;
std::cout<<"Program 1: locked. Now sleep for "<< SLEEP_TIME_IN_SECOND << "n";
sleep(SLEEP_TIME_IN_SECOND);
}
std::cout<<"unlockedn";
}
catch(interprocess_exception &ex){
std::cout << ex.what() << std::endl;
return 1;
}
return 0;
}
程序2:
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <fstream>
#include <iostream>
#include <cstdio>
int main ()
{
using namespace boost::interprocess;
try{
//Open or create the named mutex
named_mutex mutex(open_or_create, "fstream_named_mutex");
{
std::cout<<"gonna lockn";
scoped_lock<named_mutex> lock(mutex);
const unsigned int SLEEP_TIME_IN_SECOND = 5;
std::cout<<"Program 2: locked. Now sleep for "<< SLEEP_TIME_IN_SECOND << "n";
sleep(SLEEP_TIME_IN_SECOND);
}
}
catch(interprocess_exception &ex){
std::cout << ex.what() << std::endl;
return 1;
}
return 0;
}
- 当回溯以零开始时,如何调试崩溃
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 内联映射初始化的动态atexit析构函数崩溃
- 执行函数时导致崩溃的变量
- 程序崩溃并显示"std::out_of_range"错误
- CoInitialize()在单独的线程上崩溃而不返回
- 如何让LLDB在成功时退出,在失败时等待
- 使用调试/崩溃报告将应用程序部署到客户端
- 为什么所有C++编译器都会崩溃或挂起此代码
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- 为什么我的多线程作业队列崩溃
- ExtractIconEx:可以工作,但偶尔会崩溃
- 为什么引用传递会导致此崩溃(C++)
- 试图创建流或fopen时程序崩溃
- 类对象数组的问题会导致崩溃
- 排序时无法执行交换操作.我做的时候它会崩溃.为什么
- 为什么要增加导致崩溃的指针
- 如何停止C 程序在等待条件时关闭时崩溃
- Boost进程间互斥锁崩溃,而不是等待锁
- 等待Boost的空闲队列.原子示例崩溃