Вызов обработчика сигналов по умолчанию напрямую из нового - PullRequest
0 голосов
/ 04 октября 2018

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

Я видел несколько сообщений на эту тему, и большинство из них предлагают переопределить обработчик сигнала обратно к исходному обработчику, а затем повторно поднять сигнал.Моя проблема с этим заключается в том, что если какой-то другой сигнал прервал мой, я больше не буду вызываться при следующем экземпляре сигнала.Для этого я нашел решение, где вы можете напрямую вызвать старый обработчик сигнала.У меня есть следующее:

/* Set up signal handler. */
if (sigaction(sigNo, &sa, &old_sa) == -1)
...
te.sigev_value.sival_ptr = my_timer_id;
timer_create(CLOCK_REALTIME, &te, my_timer_id);
...

static void
my_timer_handler(int sig, siginfo_t *si, void *uc) {
    timer_t *tidp = si->si_value.sival_ptr;
    if ( *tidp == my_timer_id ) {
        // do my stuff
    } else {
        if (old_sa.sa_sigaction) {
            (*old_sa.sa_sigaction)(sig, si, uc);
        } else if(old_sa.sa_handler)
            (*old_sa.sa_handler)(sig);
    }
}

Но это тоже недостаток - в соответствии с man-страницей для sigaction:

В некоторых архитектурах участвует объединение: doне присваивается как sa_handler, так и sa_sigaction.

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

1 Ответ

0 голосов
/ 04 октября 2018

Я думаю, что использование sigevent структурного параметра timer_create- было бы лучшим решением.Вы можете увидеть этот ответ в качестве примера: https://stackoverflow.com/a/38356989/8067109

Если вы хотите сделать это таким образом, вы должны установить флажок SA_SIGINFO.Флаг SA_SIGINFO указывает sigaction () использовать поле sa_sigaction.

Таким образом, оно должно быть

if (old_sa.sa_flags & SA_SIGINFO) {
       (*old_sa.sa_sigaction)(sig, si, uc);
 else 
       (*old_sa.sa_handler)(sig);
...