boost managed_shared_memory find() 方法永远卡在互斥锁上
boost managed_shared_memory find() method stuck on mutex forever
我有以下程序,这是它应该做的:
- open/create一个共享内存段
- 对该托管共享内存段调用 find() 以查找对象
- 如果没有找到,实例化它
- 如果找到,则转储内容
我是这样测试的:
- 运行 该程序的一个实例合二为一 window
- 它创建共享内存段并实例化对象
- 永远等待(不确定是否需要,只是添加它以确保 linux 不会在程序退出时立即释放共享内存)
运行 同一程序的另一个实例并期望它找到对象(这就是它卡住的地方)
class data_store {
public:
data_store(uint32_t id, const char *name, bool safe) {
id_ = id;
strncpy(name_, name, sizeof(name_));
safe_ = safe;
}
~data_store() {}
uint32_t id(void) const { return id_; }
const char *name(void) const { return name_; }
private:
char name_[32];
bool safe_;
uint32_t id_;
};
int
main ()
{
managed_shared_memory *test_shmseg;
data_store *ds;
try {
test_shmseg = new managed_shared_memory(open_or_create, "seg2", 2048);
} catch (std::exception ex) {
std::cerr << ex.what() << '\n';
}
assert(test_shmseg != NULL);
try {
std::cout << "Free size " << test_shmseg->get_free_memory() << std::endl;
std::pair<data_store *, std::size_t> dsdir =
test_shmseg->find<data_store>("Datastore");
if (dsdir.first == NULL) {
// instantiate a data store
std::cout << "Instantiating data store" << std::endl;
ds =
test_shmseg->construct<data_store>("DataStore")(1,
std::string("ds").c_str(), true);
if (ds == NULL) {
std::cout << "Failed to construct Datastore" << std::endl;
exit(1);
}
} else {
std::cout << "Datastore found" << std::endl;
ds = dsdir.first;
}
std::cout << "Data store id " << ds->id() << std::endl;
std::cout << "Data store name " << ds->name() << std::endl;
} catch (boost::interprocess::bad_alloc &ex) {
std::cerr << ex.what() << '\n';
}
while (1); // wait for the other instance of this program to find the created segment and dump contents
}
我无法弄清楚为什么第二个实例能够打开共享内存段但总是卡在互斥锁上
(gdb) bt
#0 0x00007ffff7bcd42d in __lll_lock_wait () from /lib64/libpthread.so.0
#1 0x00007ffff7bc8de6 in _L_lock_870 () from /lib64/libpthread.so.0
#2 0x00007ffff7bc8cdf in pthread_mutex_lock () from /lib64/libpthread.so.0
#3 0x0000000000403d6d in boost::interprocess::ipcdetail::posix_recursive_mutex::lock (this=0x7ffff7ff8070)
at /usr/include/boost/interprocess/sync/posix/recursive_mutex.hpp:90
#4 0x0000000000403e52 in boost::interprocess::interprocess_recursive_mutex::lock (this=0x7ffff7ff8070)
at /usr/include/boost/interprocess/sync/interprocess_recursive_mutex.hpp:163
#5 0x0000000000408457 in boost::interprocess::scoped_lock<boost::interprocess::interprocess_recursive_mutex>::lock
(this=0x7fffffffdf30) at /usr/include/boost/interprocess/sync/scoped_lock.hpp:284
#6 0x00000000004073b0 in boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::priv_get_lock (this=0x7ffff7ff8010, use_lock=true)
at /usr/include/boost/interprocess/segment_manager.hpp:1315
#7 0x00000000004069ea in boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::priv_generic_find<char> (this=0x7ffff7ff8010, name=0x41c4a5 "Datastore", index=..., table=...,
length=@0x7fffffffe098: 0, is_intrusive=..., use_lock=true)
at /usr/include/boost/interprocess/segment_manager.hpp:844
#8 0x0000000000405f1e in boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::priv_find_impl<data_store> (this=0x7ffff7ff8010, name=0x41c4a5 "Datastore", lock=true)
at /usr/include/boost/interprocess/segment_manager.hpp:724
#9 0x0000000000405309 in boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::find<data_store> (this=0x7ffff7ff8010, name=...)
at /usr/include/boost/interprocess/segment_manager.hpp:434
#10 0x00000000004044ea in boost::interprocess::ipcdetail::basic_managed_memory_impl<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index, 16ul>::find<data_store> (this=0x63ec20, name=...)
at /usr/include/boost/interprocess/detail/managed_memory_impl.hpp:346
#11 0x00000000004040f7 in boost::interprocess::basic_managed_shared_memory<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::int---Type <return> to continue, or q <return> to quit---
erprocess::iset_index>::find<data_store> (this=0x63ec20, name=...)
at /usr/include/boost/interprocess/managed_shared_memory.hpp:212
感谢任何帮助。
- waits forever (not sure if this is needed, just added it to make sure linux doesn't free that shared memory as soon as the program exits)
不,这不是必需的。共享内存是 shared。它会保留,除非你明确地 remove()
它。
评论
您至少有一处不一致:对象的名称是 "Datastore"
或 "DataStore"
- 确保拼写匹配。
除此之外,我认为
- 您可能不想要 "array-style" 分配,您正在(无意中?)使用
- 您最好使用
find_or_construct
,它确实消除了潜在的 race-condition(time-of-check vs time-of-use window 在查找和创建新实例之间, 分别).
除此之外,我看不出有任何直接的挂起原因。也许您可以尝试手动删除一次共享对象,然后使用以下简化程序 re-test:
#include <boost/interprocess/managed_shared_memory.hpp>
#include <iostream>
#include <cassert>
namespace bip = boost::interprocess;
class data_store {
public:
data_store(uint32_t id, const char *name, bool safe) :
id_(id), safe_(safe)
{
id_ = id;
assert(name && strlen(name) < (sizeof(name_)-1));
strncpy(name_, name, sizeof(name_));
safe_ = safe;
}
uint32_t id() const { return id_; }
const char *name() const { return name_; }
private:
char name_[32] = {0};
uint32_t id_;
bool safe_;
};
int main () try {
bip::managed_shared_memory seg(bip::open_or_create, "seg2", 2048);
data_store ds = *seg.find_or_construct<data_store>("DataStore")(1, "ds", true);
std::cout << "Free size " << seg.get_free_memory() << std::endl;
std::cout << "Data store name " << ds.name() << std::endl;
} catch (std::exception ex) {
std::cerr << ex.what() << '\n';
}
它包含一些样式修复以及对名称长度的额外断言。
注意:在 Coliru 上使用 managed_mapped_file
,因为 manged_shared_memory
在 Coliru 上不可用。
打印:
Free size 1712
Data store name ds
-rw-r--r-- 1 2001 2000 2.0K Mar 5 12:26 seg2
Free size 1712
Data store name ds
我有以下程序,这是它应该做的:
- open/create一个共享内存段
- 对该托管共享内存段调用 find() 以查找对象
- 如果没有找到,实例化它
- 如果找到,则转储内容
我是这样测试的:
- 运行 该程序的一个实例合二为一 window
- 它创建共享内存段并实例化对象
- 永远等待(不确定是否需要,只是添加它以确保 linux 不会在程序退出时立即释放共享内存)
运行 同一程序的另一个实例并期望它找到对象(这就是它卡住的地方)
class data_store { public: data_store(uint32_t id, const char *name, bool safe) { id_ = id; strncpy(name_, name, sizeof(name_)); safe_ = safe; } ~data_store() {} uint32_t id(void) const { return id_; } const char *name(void) const { return name_; } private: char name_[32]; bool safe_; uint32_t id_; }; int main () { managed_shared_memory *test_shmseg; data_store *ds; try { test_shmseg = new managed_shared_memory(open_or_create, "seg2", 2048); } catch (std::exception ex) { std::cerr << ex.what() << '\n'; } assert(test_shmseg != NULL); try { std::cout << "Free size " << test_shmseg->get_free_memory() << std::endl; std::pair<data_store *, std::size_t> dsdir = test_shmseg->find<data_store>("Datastore"); if (dsdir.first == NULL) { // instantiate a data store std::cout << "Instantiating data store" << std::endl; ds = test_shmseg->construct<data_store>("DataStore")(1, std::string("ds").c_str(), true); if (ds == NULL) { std::cout << "Failed to construct Datastore" << std::endl; exit(1); } } else { std::cout << "Datastore found" << std::endl; ds = dsdir.first; } std::cout << "Data store id " << ds->id() << std::endl; std::cout << "Data store name " << ds->name() << std::endl; } catch (boost::interprocess::bad_alloc &ex) { std::cerr << ex.what() << '\n'; } while (1); // wait for the other instance of this program to find the created segment and dump contents }
我无法弄清楚为什么第二个实例能够打开共享内存段但总是卡在互斥锁上
(gdb) bt #0 0x00007ffff7bcd42d in __lll_lock_wait () from /lib64/libpthread.so.0 #1 0x00007ffff7bc8de6 in _L_lock_870 () from /lib64/libpthread.so.0 #2 0x00007ffff7bc8cdf in pthread_mutex_lock () from /lib64/libpthread.so.0 #3 0x0000000000403d6d in boost::interprocess::ipcdetail::posix_recursive_mutex::lock (this=0x7ffff7ff8070) at /usr/include/boost/interprocess/sync/posix/recursive_mutex.hpp:90 #4 0x0000000000403e52 in boost::interprocess::interprocess_recursive_mutex::lock (this=0x7ffff7ff8070) at /usr/include/boost/interprocess/sync/interprocess_recursive_mutex.hpp:163 #5 0x0000000000408457 in boost::interprocess::scoped_lock<boost::interprocess::interprocess_recursive_mutex>::lock (this=0x7fffffffdf30) at /usr/include/boost/interprocess/sync/scoped_lock.hpp:284 #6 0x00000000004073b0 in boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::priv_get_lock (this=0x7ffff7ff8010, use_lock=true) at /usr/include/boost/interprocess/segment_manager.hpp:1315 #7 0x00000000004069ea in boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::priv_generic_find<char> (this=0x7ffff7ff8010, name=0x41c4a5 "Datastore", index=..., table=..., length=@0x7fffffffe098: 0, is_intrusive=..., use_lock=true) at /usr/include/boost/interprocess/segment_manager.hpp:844 #8 0x0000000000405f1e in boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::priv_find_impl<data_store> (this=0x7ffff7ff8010, name=0x41c4a5 "Datastore", lock=true) at /usr/include/boost/interprocess/segment_manager.hpp:724 #9 0x0000000000405309 in boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::find<data_store> (this=0x7ffff7ff8010, name=...) at /usr/include/boost/interprocess/segment_manager.hpp:434 #10 0x00000000004044ea in boost::interprocess::ipcdetail::basic_managed_memory_impl<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index, 16ul>::find<data_store> (this=0x63ec20, name=...) at /usr/include/boost/interprocess/detail/managed_memory_impl.hpp:346 #11 0x00000000004040f7 in boost::interprocess::basic_managed_shared_memory<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::int---Type <return> to continue, or q <return> to quit--- erprocess::iset_index>::find<data_store> (this=0x63ec20, name=...) at /usr/include/boost/interprocess/managed_shared_memory.hpp:212
感谢任何帮助。
- waits forever (not sure if this is needed, just added it to make sure linux doesn't free that shared memory as soon as the program exits)
不,这不是必需的。共享内存是 shared。它会保留,除非你明确地 remove()
它。
评论
您至少有一处不一致:对象的名称是 "Datastore"
或 "DataStore"
- 确保拼写匹配。
除此之外,我认为
- 您可能不想要 "array-style" 分配,您正在(无意中?)使用
- 您最好使用
find_or_construct
,它确实消除了潜在的 race-condition(time-of-check vs time-of-use window 在查找和创建新实例之间, 分别).
除此之外,我看不出有任何直接的挂起原因。也许您可以尝试手动删除一次共享对象,然后使用以下简化程序 re-test:
#include <boost/interprocess/managed_shared_memory.hpp>
#include <iostream>
#include <cassert>
namespace bip = boost::interprocess;
class data_store {
public:
data_store(uint32_t id, const char *name, bool safe) :
id_(id), safe_(safe)
{
id_ = id;
assert(name && strlen(name) < (sizeof(name_)-1));
strncpy(name_, name, sizeof(name_));
safe_ = safe;
}
uint32_t id() const { return id_; }
const char *name() const { return name_; }
private:
char name_[32] = {0};
uint32_t id_;
bool safe_;
};
int main () try {
bip::managed_shared_memory seg(bip::open_or_create, "seg2", 2048);
data_store ds = *seg.find_or_construct<data_store>("DataStore")(1, "ds", true);
std::cout << "Free size " << seg.get_free_memory() << std::endl;
std::cout << "Data store name " << ds.name() << std::endl;
} catch (std::exception ex) {
std::cerr << ex.what() << '\n';
}
它包含一些样式修复以及对名称长度的额外断言。
注意:在 Coliru 上使用 managed_mapped_file
,因为 manged_shared_memory
在 Coliru 上不可用。
打印:
Free size 1712
Data store name ds
-rw-r--r-- 1 2001 2000 2.0K Mar 5 12:26 seg2
Free size 1712
Data store name ds