c++ - 共享内存中的健壮互斥体不是那么健壮
问题描述
当通过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;
}
问题场景
场景一:
- 启动过程 A
- 启动进程 B(未收到信号)
场景二:
- 启动流程 B
- 启动流程A(此时工作)
- 重启进程B(信号停止接收)
问题:
- 我是否正确使用了 boost 的 managed_shared_memory 对象?
- 我是否正确配置了互斥锁?
环境:
- Linux 通过 Ubuntu 18.04.3 LTS
- 海合会 v8.3.0
- 升压 v1.55
更新: @Jorge Bellon 发现了 mutex/condition_variable 被初始化两次的问题。解决后,程序现在在 CV 中被卡住时,堆栈跟踪显示为:
进程_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
进程_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
如果从不调用 remove(),即使程序终止,共享内存也会继续存在。共享内存是否自动删除取决于底层操作系统。Windows 和许多 Unix 操作系统,包括 Linux,在系统重新启动后会自动删除共享内存。
因此,进程 A 尝试在调用中获取condvar 内部互斥锁pthread_cond_wait
,但它在之前的运行中已经被锁定。而且因为你没有退出逻辑,你肯定会杀死进程,因此永远不会释放锁。过程 B 也是如此。
您创建的互斥锁是健壮的互斥锁这一事实无关紧要。因为它不是你被锁定等待。...但我实际上不确定你还在等什么。不确定 condvar 内部 futex 的属性是什么。需要进一步调查。但从观察到的行为来看,它并不稳健。
顺便说一句,您在进程 B 中获得但不使用共享互斥锁。但也许,只是也许,您应该在不锁定互斥锁的情况下调用 pthread_cond_signal
还有一件事:pthread_cond_timedwait
可以返回EOWNERDEAD
,您必须在您的wait_for_cv()
推荐阅读
- css - 如何使用 vuetify2 使所有 v-card 等高
- wordpress - How to display excerpt for custom post type
- html - form with multi select option and a search box
- python - 在 Python 中更改电子邮件正文的某些颜色
- php - Getting 502 while deploy a Laravel app to AWS Elasticbeanstalk with Nginx
- javascript - How to use Crypto JS AES component with only core file and not rollup?
- c++ - LList is not a template
- excel - 将值与表中的值进行比较
- javascript - How to convert an string dot notation in to an object reference, not nested
- go - Not able to install fabric-sdk-go and its dependencies