Проблема с сигналами, таймер (SIGEV_SIGNAL) - PullRequest
2 голосов
/ 27 апреля 2011

У меня есть небольшой фрагмент кода, где я использовал таймер POSIX: timer_create ().Таймер создается с использованием подхода сигнала (SIGEV_SIGNAL), поскольку SIGEV_THREAD не поддерживается на нашей платформе.Когда таймер истекает, он генерирует сигнал, SIGUSR1, чтобы уведомить об истечении срока действия, и есть соответствующий обработчик, чтобы перехватить этот сигнал, внутри этого обработчика (в реальной программе, не показанной в коде) у меня есть флаг, который устанавливает,как только сигнал, заданный таймером, перехвачен.

До этого все в порядке: Проблема в том, что если тестовая программа также генерирует тот же сигнал, что и таймер (в данном случае SIGUSR1), то тот жефлаг установлен, а не по таймеру.Таким образом, нет никакого способа различить, является ли сигнал, полученный в обработчике сигналов, сигналом таймера или любой другой тестовой программы.

Можете ли вы помочь мне решить эту проблему?

Заранее спасибо.

enter code here
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <string.h>


void sig_handlerTimer1(int);

time_t timerid;
int main()
{
     int i;
     static struct sigaction sa;


     static struct sigevent sevp;  // argument to timer_create
     static struct itimerspec its; // argument to timer_gettime

     memset (&sevp, 0, sizeof (struct sigevent));
     sevp.sigev_value.sival_ptr = &timerid;
     sevp.sigev_notify = SIGEV_SIGNAL;
     sevp.sigev_notify_attributes = NULL;
     sevp.sigev_signo = SIGUSR1;
     sevp.sigev_notify_function=sig_handlerTimer1;

     /* Setting timer interval */
     its.it_interval.tv_sec = 0;
     its.it_interval.tv_nsec = 0;

     /* Setting timer expiration */
     its.it_value.tv_sec = 2;  // First expiry after 1 sec
     its.it_value.tv_nsec = 0;

     /* Setting the signal handlers before invoking timer*/
     sa.sa_handler = sig_handlerTimer1;
     sa.sa_flags = 0;
     sigaction(SIGUSR1, &sa, NULL);

     if (timer_create(CLOCK_REALTIME, &sevp, &timerid) == -1)
     {
             fprintf(stderr, "LeakTracer (timer_trackStartTime): timer_create failed   to create timer. " \
                    "Leak measurement will be for entire duration of the execution   period:%s \n", strerror(errno));
            return;

      }

     if (timer_settime(timerid, 0, &its, NULL) == -1)
     {
             fprintf(stderr, "LeakTracer (timer_trackStartTime): timer_settime failed  to set the timer. " \
                    "Leak measurement will be for entire duration of execution period:%s \n", strerror(errno));
             return;

      }

      for(i=0; i<10; i++)
      {
             printf("%d\n",i);
             if(i==3) {
                 kill(getpid(), SIGUSR1); // SIGUSR1 also generated by test program  which reaches same handler and sets flag (THIS IS UN-DESIRABLE)
              }
             sleep(1);
       }

  }

  void sig_handlerTimer1(int signum)
  {

     int flag = 1;
     printf("Caught signal: %d\n",signum); // How to understand this signal caught, is that of test program of timer expiry?
     if (timer_delete(timerid) < 0)
     {
             fprintf(stderr, "timer deletion failed. " \
                     "This may result in some memory leaks (sig_handlerTimer1):%s \n", strerror(errno));
      }
   }

Добавлено: Есть ли какой-нибудь способ узнать в обработчике, истек ли таймер на самом деле или нет, как только сигнал будет пойман?

Ответы [ 3 ]

4 голосов
/ 27 апреля 2011

Вы можете определить причину сигнала, установив обработчик сигнала с флагом SA_SIGINFO и элементом sa_sigaction struct sigaction, затем используя элемент si_code siginfo_t *, передаваемый обработчику сигнала. , Если это SI_TIMER, то сигнал был сгенерирован истечением таймера.

0 голосов
/ 10 апреля 2012

Здесь - это почти тот же вопрос, на который он отвечает.В этом решении он устанавливает указатель на sigval union, вы также можете установить любое значение int.Это значение можно проверить в обработчике, если значение совпадает с заданным вами, то это ваш сигнал.Ниже приведено определение sigval union:

union sigval {
    int sival_int;
    void *sival_ptr;
}; 

, вы можете установить seg.sigev_value.sival_int = yourint и в обработчике проверить то же значение, сравнив этот способ:

if(si->si_value.sival_int == yourint)
 printf("My event");
else
 printf("It's not");

Надеюсь, это поможет

0 голосов
/ 27 апреля 2011

Вы, вероятно, будете в порядке, так как единственный способ получить SIGUSR1 - это сгенерировать его самостоятельно, либо в процессе, используя системный вызов kill() или в результате истечения таймера, либо изкомандная строка с использованием команды kill.

Существует также SIGUSR2, который можно использовать для любых дополнительных целей.

...