2010-03-05 4 views
3

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

+0

Часто плохой идеей иметь системные вызовы от обработчиков сигналов ... вы уверены, что вы здесь защищены? – JXG

+0

Да, это проблема. Я хочу избежать небезопасных системных вызовов *, если * Я в обработчике сигналов, но имею их, если код вызывается, когда я не в обработчике сигналов. –

ответ

2

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

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

+0

Это интересный момент о longjmp (или siglongjmp); Я должен подумать об этом и о том, что на самом деле означает быть в обработчике сигналов. Моя основная забота - знать, могу ли я быть в какой-то другой части кода, которая могла бы удерживать блокировку, и поскольку такого рода вещи не были бы безопасными для setjmp/longjmp, я вообще не использую функции jmp они могут вызвать эту проблему. Мне нравится предложение sigaction/sa_mask, хотя это похоже на то, что я точно ищу. –

0

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

+1

Я думаю, что sigpending установлен только до подачи сигнала. После ввода обработчика сигнала сигнал не устанавливается как «ожидающий». –

3

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


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

+0

Кроме того, вы пытаетесь сделать это извращенным. Вы не перегружаетесь от обработчика сигнала (см. Sigjump et.al). Кроме того, функции stdio не считаются безопасными по сигналу (они называются malloc() и т. Д.) – wildplasser

+0

К сожалению, я прокомментировал программу R., которая должна была быть извращенной. Сожалею! – wildplasser

+0

Мне нравится этот ответ в том, что он дает хороший способ сделать что-то, но я действительно не хочу добавлять отдельный процесс и отправлять все сообщения журнала через канал, если мне это не нужно.Я все еще хочу, чтобы был простой способ определить, был ли я в обработчике сигналов; кажется, что ОС не должно быть сложно знать. –

Смежные вопросы