【问题标题】:boost managed_shared_memory find() method stuck on mutex foreverboost managed_shared_memory find() 方法永远卡在互斥体上
【发布时间】:2018-03-05 04:36:21
【问题描述】:

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

  • 打开/创建共享内存段
  • 在该托管共享内存段上调用 ​​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
    

感谢任何帮助。

【问题讨论】:

    标签: boost shared-memory


    【解决方案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
    

    【讨论】:

    • 谢谢..这行得通..我删除了现有的段并修复了对象的名称,以便在 DataStore/Datastore 之间保持一致并且有效。如果对象不存在,我希望不会像那样卡住。
    • 如果删除段是必不可少的步骤,则可能意味着您的进程因嵌入式互斥锁锁定而崩溃。没有真正的(便携式)解决方案:stackoverflow.com/questions/15772768/…
    猜你喜欢
    • 1970-01-01
    • 2013-08-09
    • 2022-12-07
    • 2022-06-13
    • 2012-12-17
    • 2021-06-10
    • 2017-02-14
    • 1970-01-01
    相关资源
    最近更新 更多