当通过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:
  • 启动过程
  • 启动进程B(未收到信号)

  • 方案2:
  • 启动进程B
  • 启动进程A(此时有效)
  • 重新启动进程B(停止接收信号)

  • 问题:
  • 我可以正确使用boost的managed_shared_memory对象吗?
  • 我是否正确配置了互斥锁?

  • 环境:
  • 通过Ubuntu 18.04.3 LTS的Linux
  • GCC v8.3.0
  • Boost v1.55

  • 更新:
    @Jorge Bellon发现了互斥锁/condition_variable初始化两次的问题。解决之后,该程序现在可以捕获简历
    锁定时,堆栈跟踪显示为:

    process_a:
    futex_wait 0x00007ffff7bc3602
    futex_wait_simple 0x00007ffff7bc3602
    __condvar_acquire_lock 0x00007ffff7bc3602
    __condvar_cancel_waiting 0x00007ffff7bc3602
    __pthread_cond_wait_common 0x00007ffff7bc40bd
    __pthread_cond_timedwait 0x00007ffff7bc40bd
    wait_until cv_utils.cpp:73
    wait_for_cv cv_utils.cpp:93
    main main_process_a.cpp:85
    __libc_start_main 0x00007ffff6fe6b97
    _start 0x000055555555734a
    

    process_b:
    futex_wait 0x00007ffff7bc44b0
    futex_wait_simple 0x00007ffff7bc44b0
    __condvar_quiesce_and_switch_g1 0x00007ffff7bc44b0
    __pthread_cond_signal 0x00007ffff7bc44b0
    main main_process_b.cpp:73
    __libc_start_main 0x00007ffff6fe6b97
    _start 0x00005555555573aa
    

    最佳答案

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



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

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

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

    10-07 19:52
    查看更多