提升managed_shared_memory find()方法永远停留在互斥锁上

时间:2018-03-05 04:36:22

标签: boost shared-memory

我有以下程序,这是它应该做的:

  • 打开/创建共享内存段
  • 在该托管共享内存段上调用find()以查找对象
  • 如果找不到,请将其实例化
  • 如果找到,只需转储内容

我按以下方式测试:

  • 在一个窗口中运行此程序的一个实例
  • 它创建共享内存片段并实例化对象
  • 永远等待(不确定是否需要这个,只是添加它以确保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
    

感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

  
      
  • 永远等待(不确定是否需要这个,只是添加它以确保linux在程序退出时不会释放该共享内存)
  •   

不,这不是必需的。共享内存共享。除非您明确remove(),否则它会保留。

评分

您至少有一个不一致:对象的名称是"Datastore""DataStore" - 请确保您的拼写匹配。

除此之外,我认为

  • 你可能不想要“数组式”分配,你是(无意中?)使用
  • 您可能最好使用find_or_construct,它确实消除了潜在的竞争条件(分别在查找和创建新实例之间的检查时间与使用时间窗口)。

除此之外,我没有看到任何挂起的直接原因。也许您可以尝试手动删除共享对象一次,并使用以下简化程序重新测试:

#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';
}

它包含一些样式修复以及名称长度上的额外断言。

<强> Live On Coliru

注意:在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