Как я восстанавливаю семафор, когда процесс, который постепенно уменьшил его для обнуления катастрофических отказов?

У меня есть несколько приложений, скомпилированных с g ++, работающий в Ubuntu. Я использую названные семафоры для координирования между различными процессами.

Все хорошо работает кроме следующей ситуации: Если один из вызовов процессов sem_wait() или sem_timedwait() постепенно уменьшать семафор и затем отказывает или уничтожается-9, прежде чем это получит шанс звонить sem_post(), тогда с того момента на, именованный семафор "неприменим".

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

Я не могу найти a sem_*() API, который мог бы сказать мне процесс, который в последний раз постепенно уменьшил его, отказал.

Я пропускаю API где-нибудь?

Вот то, как я открываю именованный семафор:

sem_t *sem = sem_open( "/testing",
    O_CREAT     |   // create the semaphore if it does not already exist
    O_CLOEXEC   ,   // close on execute
    S_IRWXU     |   // permissions:  user
    S_IRWXG     |   // permissions:  group
    S_IRWXO     ,   // permissions:  other
    1           );  // initial value of the semaphore

Вот то, как я постепенно уменьшаю его:

struct timespec timeout = { 0, 0 };
clock_gettime( CLOCK_REALTIME, &timeout );
timeout.tv_sec += 5;

if ( sem_timedwait( sem, &timeout ) )
{
    throw "timeout while waiting for semaphore";
}
47
задан Stéphane 13 January 2010 в 01:38
поделиться

5 ответов

Оказывается, надежного восстановления семафора нет. Конечно, любой может post_sem() к названному семафору, чтобы снова увеличить счетчик до нуля, но как сказать, когда такое восстановление необходимо? Предоставляемый API слишком ограничен и никак не указывает, когда это произошло.

Остерегайтесь также инструментов ipc -- общие инструменты ipcmk, ipcrm и ipcs предназначены только для устаревших семафоров SysV. В частности, они не работают с новыми семафорами POSIX.

Но похоже, что есть и другие вещи, которые могут быть использованы для блокировки, которые операционная система автоматически освобождает, когда приложение умирает таким образом, что не может быть поймано обработчиком сигнала. Два примера: прослушивающий сокет, привязанный к определённому порту, или блокировка на определённом файле.

Я решил, что блокировка файла - это то решение, которое мне нужно. Поэтому вместо вызова sem_wait() и sem_post() я использую:

lockf( fd, F_LOCK, 0 )

и

lockf( fd, F_ULOCK, 0 )

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

Спасибо за помощь, ребята.

40
ответ дан 26 November 2019 в 19:52
поделиться

Вы должны быть в состоянии найти его из оболочки, используя LSOF . Тогда, возможно, вы можете удалить его?

Обновление

Ах да ... Man -k Semaphore к спасению.

Кажется, что вы можете использовать IPCRM , чтобы избавиться от семафора. Кажется, вы не первые с этой проблемой.

2
ответ дан 26 November 2019 в 19:52
поделиться

Если процесс был убит, то не будет никакого прямого способа определить, что он ушел.

Вы можете управлять какой-то проверкой периодической целостности во всех семафорах, которые у вас есть - используйте SEMCTL (cmd = getpid), чтобы найти PID для последнего процесса, который касался каждого семафора в состоянии, который вы описываете, Затем проверьте, остается ли этот процесс все еще вокруг. Если нет, выполните очистку.

1
ответ дан 26 November 2019 в 19:52
поделиться

Это типичная проблема при управлении семафорами. Некоторые программы используют один процесс для управления инициализацией / удалением семафора. Обычно этот процесс делает только это и больше ничего. Ваши другие приложения могут дождаться, пока не будет доступен семафор. Я видел это сделано с помощью API типа SYSV, но не с POSIX. Подобно тому, что « утка упоминается, используя флаг Sem_undo в вашем SEMOP ().


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

5
ответ дан 26 November 2019 в 19:52
поделиться

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

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

Также семафон обычно перечислен под / dev / shm, и вы можете удалить его.

SYSV SEMAPHORS более любые для этого сценария. Вы можете указать SEM_undo, в котором система откажется от изменения в семафоре, сделанном процессом, если он умирает. У них также есть возможность сказать вам последний идентификатор процесса, чтобы изменить семафор.

2
ответ дан 26 November 2019 в 19:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: