16

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

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

4

5 回答 5

33

似乎以健壮的互斥锁的形式提供了确切的答案。

根据 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

于 2010-10-16T22:40:35.703 回答
9

如果您在 Linux 或类似的环境中工作,请考虑使用命名信号量而不是(我假设是)pthreads 互斥锁。我认为没有办法确定 pthreads 互斥锁的锁定 PID,除了建立自己的注册表并将其放入共享内存中。

于 2009-11-09T11:01:48.700 回答
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 直到后来才告诉你),然后第二个程序立即获得锁并继续。

于 2009-11-13T21:41:08.603 回答
1

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


您可以使用这种方法。1) 锁定 POSIX 共享互斥锁 2) 将进程 ID 保存在共享内存中。3) 解锁共享互斥锁 4) 在正确退出时清理进程 ID

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

更新以回答评论:

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

于 2009-11-09T10:55:52.197 回答
0

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

操作系统释放进程已打开的所有资源,无论它是终止还是正常退出。

于 2009-11-09T10:52:13.103 回答