Как управлять общим семафором POSIX с асинхронными сигналами в многопоточном приложении

Я должен написать потокобезопасную библиотеку, которая использует семафор POSIX (используется как мьютекс с начальным значением = 1) для синхронизации. Я обнаружил некоторые проблемы для правильного управления асинхронными сигналами. У меня есть приложение, которое связывается с этой статической библиотекой, и приложение (многопоточное) вызывает функции библиотеки. Доступ к некоторым внутренним структурам контролируется семафором posix (он является внутренним для библиотеки):

void library_func1(lib_handler *h)
{
   sem_wait(sem);
   /* do some stuff with global data */
   sem_post(sem);
}

void library_func2(lib_handler *h)
{
   sem_wait(sem);
   /* do some stuff with global data */
   sem_post(sem);
}

void library_close(lib_handler *h)
{
   ...
}

Что добавить, если асинхронный сигнал, скажем, SIGINT, возникает, когда один поток блокирует семафор? Если я перезапущу приложение, у меня будет тупик, потому что семафор существует, и его значение 0, Есть функция library_close это может освободить семафор, когда асинхронный сигнал повышен, но это лучший способ сделать и проверить это (я думаю, что эта функция будет безопасной для сигнала, только если после exit)? В многопоточных приложениях обычно рекомендуется иметь единый диспетчер потоков для всех сигналов: этот поток должен находиться в библиотеке или можно запустить его в приложении?

Спасибо вам всем.

2 ответа

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

Есть еще небольшая гонка с этим, так как процесс взятия блокировки может умереть сразу после блокировки, но до написания pid. AFAIK, нет никакого способа избежать этого, используя семафоры. (Это может сработать, если у вас есть реализация блокировки, где pid атомарно записывается в переменную блокировки в aquire, но вам, вероятно, придется написать это самостоятельно.)

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

Другие вопросы по тегам