繁体   English   中英

Boost进程间named_mutex导致分段错误

[英]Boost Interprocess named_mutex causing segmentation fault

我正在使用boost进程间共享内存,但是当我尝试使用boost :: interprocess :: scoped_lock进行boost :: interprocess:named_mutex时,很少会出现分段错误。

我只在运行编写器进程。 该进程拥有共享内存,并且不会销毁它(除非应用程序关闭)。 该应用程序使用SharedDataCommon类(请参阅问题底部)创建共享内存,该类对所有boost内部工作进行加密,然后稍后我调用write(),该方法尝试检索named_mutex,但它会分割故障。

分段错误发生在

boost / interprocess / sync / posix / named_semaphore.hpp

第63行:

void wait()
   {  semaphore_wait(mp_sem); }     // seg faults here

好像有人在应用程序运行时更改了信号灯的权限,除非他们没有。 是否有日志检查分段错误之前是否更改了权限?

在写之前获取作用域锁时,发生分段错误:

bool write(const std::vector<T>& vec, const bool clearFirst = false)
{
    bip::scoped_lock<bip::named_mutex> lock(*sdc.mutex);   // seg faults here

    try
    {
        sdc.vec->reserve(sdc.vec->size() + vec.size());
    }
    catch(std::exception& e)
    {
        std::cout << "Not enough room to write elements" << std::endl;
        return false;
    }

    if(clearFirst)
    {
        sdc.vec->clear();
    }

    for(const auto& item : vec)
    {
        sdc.vec->push_back(item);
    }

    sdc.cond_empty->notify_all();

    return true;
} 

sdc是SharedDataCommon的一个实例(请参见下文),其中封装了boost :: interprocess组件。

我设置了临时设置的umask,以便多个Linux用户可以读取共享内存。

template<typename T>
struct SharedDataCommon
{
    using ShmemAllocator = bip::allocator<T, bip::managed_shared_memory::segment_manager>;
    using MyVector = bip::vector<T, ShmemAllocator>;

    void initialise(const std::string& tag, const int numBytes, const bool ownMemory)
    {
        const std::string sharedMemoryName = tag + "_shared_memory";
        const std::string sharedVectorName = tag + "_shared_vector";
        const std::string sharedMutexName = tag + "_shared_mutex";
        const std::string sharedCVName = tag + "_shared_cv";

        tag_name = tag;
        shared_memory_name = sharedMemoryName;
        shared_mutex_name = sharedMutexName;
        shared_vector_name = sharedVectorName;
        shared_cv_name = sharedCVName;
        destroy_memory = ownMemory;

        if(ownMemory)
        {
            destroyMemory(tag);
        }

        createMemory(numBytes);
    }

    void createMemory(const int numBytes)
    {
        const mode_t old_umask = umask(0);

        bip::permissions perm;
        perm.set_unrestricted();
        segment.reset(new bip::managed_shared_memory(bip::open_or_create, shared_memory_name.c_str(), numBytes, 0, perm));

        mutex.reset(new bip::named_mutex(bip::open_or_create, shared_mutex_name.c_str(), perm));

        const ShmemAllocator alloc_inst(segment->get_segment_manager());
        vec = segment->find_or_construct<MyVector>(shared_vector_name.c_str())(alloc_inst);

        cond_empty.reset(new bip::named_condition(bip::open_or_create, shared_cv_name.c_str(), perm));

        umask(old_umask);
    }

    static void destroyMemory(const std::string& tag)
    {
        const std::string sharedMemoryName = tag + "_shared_memory";
        const std::string sharedMutexName = tag + "_shared_mutex";
        const std::string sharedCVName = tag + "_shared_cv";

        bip::named_mutex::remove(sharedMutexName.c_str());
        bip::named_condition::remove(sharedCVName.c_str());     
        bip::shared_memory_object::remove(sharedMemoryName.c_str());
    }

    ~SharedDataCommon()
    {
        if(destroy_memory)
        {
            destroyMemory(tag_name);
        }
    }

    std::shared_ptr<bip::named_mutex>           mutex{nullptr};
    MyVector*                                   vec{nullptr};
    std::shared_ptr<bip::managed_shared_memory> segment{nullptr};
    std::shared_ptr<bip::named_condition>       cond_empty;
    bool                                        destroy_memory{false};
    std::string                                 shared_vector_name;
    std::string                                 shared_mutex_name;
    std::string                                 shared_cv_name;
    std::string                                 shared_memory_name;
    std::string                                 tag_name;
};

我没有看到任何能解释为什么有时会出现问题的信息?

当您只需要在共享内存段中使用未命名的进程间同步原语时,为什么要使用所有这些单独的命名实体? 请参阅例如Boost Interprocess共享内存删除,权限和输出文件 (第二个示例)。

这立即消除了在检索所有共享对象与实际在基元上进行同步之间的竞争条件。


我可以合理地看到位于共享库之外的唯一一件事是named_mutex因此您可以同步共享内存段的实际创建。 但是,查看您的代码似乎无法完全做到这一点:

    segment.reset(new bip::managed_shared_memory(bip::open_or_create, shared_memory_name.c_str(), numBytes, 0, perm));

    mutex.reset(new bip::named_mutex(bip::open_or_create, shared_mutex_name.c_str(), perm));

互斥锁在段之后创建。 现在,当您控制服务器和客户端的启动顺序时,这可能不是问题。 但是,在这种情况下,显然不需要单独的named-mutex。


同样令人担忧的是,您在没有任何同步的情况下破坏了内存:

destroyMemory(tag);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM