一个用户崩溃时共享内存中的互斥锁?

时间:2009-11-09 10:47:28

标签: c++ c linux mutex shared-memory

假设进程正在共享内存中创建互斥锁并锁定它并在互斥锁被锁定时转储核心。

现在在另一个过程中,如何检测互斥锁已被锁定但不属于任何进程?

5 个答案:

答案 0 :(得分:31)

似乎确切的答案是以强大的互斥体的形式提供的。

根据POSIX,可以使用pthread_mutexattr_setrobust()初始化pthread互斥锁。如果持有互斥锁的进程随后死亡,则获取它的下一个线程将接收EOWNERDEAD(但仍然成功获取互斥锁),以便它知道执行任何清理。然后,它需要使用pthread_mutex_consistent()通知所获取的互斥锁再次一致。

显然你需要内核和libc支持才能工作。在Linux上,这背后的内核支持称为“健壮的futexes”,我发现对glibc HEAD应用的用户空间更新的引用。

实际上,至少在Linux世界中,对此的支持似乎还没有过滤掉。如果这些函数不可用,你可能会在那里找到pthread_mutexattr_setrobust_np(),据我所知,它似乎是一个提供相同语义的非POSIX前身。我在Solaris文档和Debian上的/usr/include/pthread.h中找到了对pthread_mutexattr_setrobust_np()的引用。

可在此处找到POSIX规范:http://www.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_setrobust.html

答案 1 :(得分:8)

如果你在Linux或类似的东西工作,请考虑使用named semaphores而不是(我假设的)pthreads互斥。我认为有一种方法可以确定pthreads互斥锁的锁定PID,而不是构建自己的注册表并将它放在共享内存中。

答案 2 :(得分:5)

基于文件的锁定(使用flock(2))怎么样?当持有它的过程消失时,它们会自动释放。

演示程序:

#include <stdio.h>
#include <time.h>
#include <sys/file.h>

void main() {
  FILE * f = fopen("testfile", "w+");

  printf("pid=%u time=%u Getting lock\n", getpid(), time(NULL));
  flock(fileno(f), LOCK_EX);
  printf("pid=%u time=%u Got lock\n", getpid(), time(NULL));

  sleep(5);
  printf("pid=%u time=%u Crashing\n", getpid(), time(NULL));
  *(int *)NULL = 1;
}

输出(为了清楚起见,我已经截断了PID并稍微计算一下):

$ ./a.out & sleep 2 ; ./a.out 
[1] 15
pid=15 time=137 Getting lock
pid=15 time=137 Got lock
pid=17 time=139 Getting lock
pid=15 time=142 Crashing
pid=17 time=142 Got lock
pid=17 time=147 Crashing
[1]+  Segmentation fault      ./a.out
Segmentation fault

第一个程序获得锁定并开始睡眠5秒钟会发生什么。 2秒后,程序的第二个实例启动,在尝试获取锁定时阻塞。 3秒后,第一个程序段错误(bash直到稍后才告诉你),然后第二个程序获得锁定并继续。

答案 3 :(得分:1)

您应该使用操作系统提供的信号量。

操作系统会释放进程已打开的所有资源,无论它是否已正常死亡。

答案 4 :(得分:1)

只有当有人有同样的想法并且会发现有关使用的讨论时,我才会删除这个错误的帖子!


您可以使用此方法。 1)锁定POSIX共享互斥锁 2)将process-id保存在共享内存中。 3)解锁共享的互斥锁 4)正确退出时清理process-id

如果进程coredumps下一个进程将发现在共享内存中有一个在步骤#2中保存的进程ID。如果操作系统中没有此进程标识的进程,则没有人拥有共享互斥锁。因此,只需要替换process-id。

更新以回复评论:

场景1:  1. P1开始  2.如果不存在,P1会创建/打开一个已命名的互斥锁  3. P1 timed_locks指定的互斥锁并成功执行(必要时等待10秒);  4. P1 coredumps  5.在coredump之后开始P2  6. P2创建/打开一个命名的互斥锁,它存在,没关系  7. P2 timed_locks指定的互斥锁并且无法锁定(必要时等待10秒);  8. P2删除指定的互斥锁  9. P2重新创建一个名为mutex&amp;锁定它