Есть ли способ проверить, нахожусь ли я в обработчике сигналов? - PullRequest
3 голосов
/ 06 марта 2010

Мне нужно работать над модулем регистрации, который можно вызывать из разных мест большого проекта. У меня проблема в том, что иногда модуль может вызываться из кода, выполняемого внутри обработчика сигнала. Обычно модуль регистрации включает данные о времени, используя localtime () и strftime (), но, конечно, эти вызовы не являются безопасными для асинхронного сигнала и могут вызывать взаимные блокировки, если вызваны из обработчика сигнала. Есть ли способ (в системе GNU / Linux) сказать, выполняется ли мой код в настоящее время в контексте обработчика сигнала, кроме, например, установки каждого обработчика сигнала во время обработки? Я думаю, что было бы лучше упростить наши обработчики сигналов, но в этом случае у меня нет выбора относительно того, где может быть вызван модуль регистрации. Было бы хорошо, если бы я мог протестировать и просто опустить информацию о временной метке, если модуль вызывается во время обработки сигнала.

Ответы [ 3 ]

3 голосов
/ 03 сентября 2011

Прежде всего, ваш вопрос («Я в обработчике сигналов?») Не имеет четко определенного ответа. Рассмотрим следующий код:

#include <setjmp.h>
#include <signal.h>

jmp_buf jb;
int foo(int s)
{
    longjmp(jb,1);
}

int main()
{
    if (setjmp(jb)) {
        puts("Am I in a signal handler now, or not?");
        return 0;
    }
    signal(SIGINT, foo);
    raise(SIGINT);
}

С учетом вышесказанного, существует методика, которую вы могли бы использовать для значимого ответа на этот вопрос для многих программ. Выберите сигнал, который вы не собираетесь использовать, и добавьте его в sa_mask для всех обрабатываемых вами сигналов, установив обработчики сигналов с помощью sigaction. Затем вы можете использовать sigprocmask, чтобы проверить текущую маску сигнала, и если указанный вами сигнал находится в маске сигнала, это означает, что обработчик сигнала был вызван и еще не возвращен (возврат приведет к восстановлению исходной маски сигнала).

3 голосов
/ 03 сентября 2011

Самый простой способ - войти через (именованный) канал (записи в PIPE_MAX являются атомарными) или через сокет UDP (то же самое). Источник сообщения может быть установлен функцией, генерирующей сообщение. Конечно, вам понадобится процесс, который фактически читает и обрабатывает сообщения, но его можно оставить вне контекста обработчика сигнала.


Кстати: вам не нужен отдельный процесс для получения сообщений, вы можете отправлять сообщения своему собственному процессу и добавлять (конец чтения) канал к fd_set (если ваша программа находится в выборке или опросе) цикл), или периодически опрашивать.

0 голосов
/ 06 марта 2010

Есть ли в вашей системе sigpending?Я не знаю, как ведет себя эта функция во время обработки сигнала.Однако, если он возвращает установленный флаг, вы можете быть пессимистичными и пропускать асинхронные небезопасные вызовы, если ожидают какие-либо сигналы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...