共享内存中健壮的互斥锁不那么健壮

时间:2019-12-18 10:17:59

标签: linux posix mutex

当通过boost::interprocesss::managed_shared_memory对象使用基于pthread的健壮互斥锁从一个进程向另一个进程发出信号时,我注意到存在以下问题:a)取决于启动顺序和/或b)行为改变时进程重新启动。问题的症结在于,在某些条件下,我的示例应用程序中的信号(通过条件变量)没有被接收。

我已经在git-https://github.com/zerodefect/mutex_example中发布了(最小)代码示例。我试图使代码示例尽可能简短,但是它仍然跨越几个文件。我希望在这种情况下可以链接到GitHub中的存储库吗?

我有2个进程-process_b:

while (true)
{
    // Notify 'Process A' every 2 seconds.
    std::this_thread::sleep_for(std::chrono::seconds(2));
    pthread_cond_signal(pCv);

    std::cout << "Info: Signaled" << std::endl;
}

仅尝试向process_a发出信号:

while (true)
{
    if (!timed_lock_mutex(pMutex, std::chrono::seconds(5)))
    {
        std::cout << "Warning: Mutex wait timeout." << std::endl;
        continue;
    }

    BOOST_SCOPE_EXIT(pMutex)
    {
        unlock_mutex(pMutex);
    } BOOST_SCOPE_EXIT_END

    if (!wait_for_cv(pCv, pMutex, std::chrono::seconds(10)))
    {
        std::cout << "Warning: Wait timeout!" << std::endl;
        continue;
    }

    std::cout << "Info: Received notification." << std::endl;
}

问题方案

方案1:

  1. 开始进程A
  2. 启动过程B(未收到信号)

方案2:

  1. 开始流程B
  2. 启动进程A(此时有效)
  3. 重新启动进程B(停止接收信号)

问题:

  1. 我是否正确使用了boost的managed_shared_memory对象?
  2. 我是否正确配置了互斥锁?

环境:

  • 通过Ubuntu 18.04.3 LTS的Linux
  • GCC v8.3.0
  • 提升v1.55

1 个答案:

答案 0 :(得分:0)

我的猜测是您的代码锁是因为您永远不会破坏共享内存 https://theboostcpplibraries.com/boost.interprocess-shared-memory

如果从不调用remove(),则即使程序终止,共享内存也会继续存在。是否自动删除共享内存取决于基础操作系统。重新启动系统后,Windows和许多Unix操作系统(包括Linux)会自动删除共享内存。

因此,过程尝试在pthread_cond_wait调用中获取 condvar内部互斥锁的锁,但是在先前的运行中已将其锁定。而且由于您没有退出逻辑,因此您肯定会杀死进程,从而永远不会释放锁。流程B同样如此。

您创建的互斥体是健壮的互斥体这一事实无关紧要。因为不是它,所以您被锁定等待。 ...但是我实际上不确定您还在等什么。不确定condvar内部futex的属性是什么。需要进一步调查。但是从观察到的行为来看,它并不可靠。

顺便说一句,您获得但不使用流程B中的共享互斥。但是也许,也许,您应该Calling pthread_cond_signal without locking mutex 还有另外一件事:pthread_cond_timedwait可以返回EOWNERDEAD,您必须检查您的wait_for_cv()

中的错误