Mutex в общей памяти при сбое одного пользователя? - программирование

Mutex в общей памяти при сбое одного пользователя?

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

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

4b9b3361

Ответ 1

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

Ответ 2

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

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

Очевидно, вам нужна поддержка как ядра, так и libc для этого. В Linux поддержка ядра позади этого называется "надежными futexes", и я нашел ссылки на обновления пользовательского пространства, применяемые к 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

Ответ 3

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

Ответ 4

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

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

Ответ 5

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


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

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

Обновить, чтобы ответить на комментарий:

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