Mutex в разделяемой памяти, когда один пользователь падает? - PullRequest
14 голосов
/ 09 ноября 2009

Предположим, что процесс создает мьютекс в разделяемой памяти, блокирует его и выдает дамп ядра, пока мьютекс заблокирован.

Теперь, в другом процессе, как определить, что мьютекс уже заблокирован, но не принадлежит ни одному процессу?

Ответы [ 5 ]

31 голосов
/ 17 октября 2010

Похоже, что точный ответ был представлен в виде надежных мьютексов.

Согласно POSIX, мьютексы pthread могут быть инициализированы как «надежные» с помощью pthread_mutexattr_setrobust (). Если процесс, удерживающий мьютекс, умирает, следующий поток, получивший его, получит EOWNERDEAD (но все же успешно получит мьютекс), чтобы он знал, что нужно выполнить любую очистку. Затем он должен уведомить, что полученный мьютекс снова согласован, используя pthread_mutex_consistent ().

Очевидно, что для работы вам нужна поддержка как ядра, так и libc. В Linux поддержка ядра называется «надежные фьютексы», и я нашел ссылки на обновления пользовательского пространства, применяемые к glibc HEAD.

На практике поддержка этого пока не просочилась, по крайней мере, в мире Linux. Если эти функции недоступны, вы можете вместо этого найти pthread_mutexattr_setrobust_np (), который, насколько я могу судить, кажется не предшественником POSIX, обеспечивающим ту же семантику. Я нашел ссылки на pthread_mutexattr_setrobust_np () как в документации по Solaris, так и в /usr/include/pthread.h для Debian.

Спецификацию POSIX можно найти здесь: http://www.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_setrobust.html

8 голосов
/ 09 ноября 2009

Если вы работаете в Linux или чем-то подобном, рассмотрите возможность использования именованных семафоров вместо (как я полагаю) мьютексов pthreads. Я не думаю, что есть способ определить PID блокировки мьютекса pthreads, за исключением создания своей собственной регистрационной таблицы и помещения ее в общую память.

5 голосов
/ 14 ноября 2009

Как насчет блокировки на основе файлов (с использованием 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 секунды первая программа segfaults (хотя bash не скажет вам об этом, пока позже), и сразу же вторая программа получает блокировку и продолжает работу.

1 голос
/ 09 ноября 2009

Я оставил этот НЕПРАВИЛЬНЫЙ пост, только если кто-то будет иметь ту же идею и найдет это обсуждение использования!

<Ч />

Вы можете использовать этот подход. 1) Блокировка общего мьютекса POSIX 2) Сохранить идентификатор процесса в общей памяти. 3) Разблокировать общий мьютекс 4) При правильном выходе очистите идентификатор процесса

Если процесс coredumps, следующий процесс обнаружит, что в общей памяти на шаге 2 сохранен идентификатор процесса. Если в ОС нет процесса с этим идентификатором процесса, то никто не владеет общим мьютексом. Так что просто необходимо заменить идентификатор процесса.

Обновление для ответа на комментарий:

Сценарий 1: 1. P1 запускается 2. P1 создает / открывает именованный мьютекс, если он не существует 3. P1 timed_locks указанный мьютекс и успешно делает это (ждет 10 секунд, если необходимо); 4. P1 coredumps 5. P2 запускается после coredump 6. P2 создает / открывает именованный мьютекс, он существует, все в порядке 7. P2 timed_locks указанный мьютекс и не может заблокировать (ждет в течение 10 секунд при необходимости); 8. P2 удалить названный мьютекс 9. P2 воссоздает именованный мьютекс и блокирует его

1 голос
/ 09 ноября 2009

Вы должны использовать семафор, предоставляемый операционной системой.

Операционная система высвобождает все ресурсы, открытые для процесса, независимо от того, уходит он или завершается изящно.

...