質問

I am a Linux newbie. I am trying to implement a simple task using clock_nanosleep. The issue is, clock_nanosleep is not setting errno to EINTR after interrupted by the signal. I have tried resetting SA_RESTART flag. But, no success. Here is my code. Thanks.

void signalHandler( int signum )
{
    printf("Interrupt signal received.\n");
}

void *periodic_thread (void *param)
{
struct itimerspec its;
struct sigevent sig;
struct timespec next, period;
sigset_t blocked;

siginfo_t si;
timer_t mytimer;
int i, j;

/* create a timer that will be used to periodically send a signal */
sig.sigev_notify = SIGEV_SIGNAL;
sig.sigev_signo = SIGUSR1;
sig.sigev_value.sival_ptr = &sig;

timer_create(CLOCK_REALTIME, &sig, &mytimer);

struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = &signalHandler;
sigaction(SIGUSR1, &sa, NULL);

/* set the periodic timer */
its.it_value.tv_sec = 8;
its.it_value.tv_nsec = 00000000; 
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0; ;
period.tv_sec = 5;
period.tv_nsec = 00000000; 

timer_settime(mytimer, 0, &its, NULL); 

printf("periodic thread started...\n");

j=1;

i = clock_gettime(CLOCK_MONOTONIC, &next);
while(1)
{
  next.tv_sec = next.tv_sec + period.tv_sec;
  next.tv_nsec = next.tv_nsec + period.tv_nsec;
  i = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next, 0);  
  printf("I am done \n");
  if((i == -1) && (errno == EINTR))
  break;
}

printf("...periodic thread end!\n");

timer_delete(mytimer);
return NULL;
}

int main()
{

  pthread_t mythread;
  pthread_attr_t myattr;

  //struct sched_param myparam;
  void *returnvalue;
  sigset_t blocked;


  /* initializes the thread attribute */
  pthread_attr_init(&myattr);


  printf("starting a periodic thread...\n");

  pthread_create(&mythread, &myattr, periodic_thread, NULL);

  pthread_attr_destroy(&myattr);

  /* wait the end of the thread we just created */
  pthread_join(mythread, &returnvalue);

  printf("ending main...\n");

return 0;
}

Output>>

  starting a periodic thread...
  periodic thread started...
  I am done 
  Interrupt signal received.
  I am done 
  I am done
  continues.. (Does not break the while(1)) 
役に立ちましたか?

解決

I figured out the issue,

Issue: Main thread was getting interrupted by a signal instead of child thread consisting clock_nanosleep.

Solution 1: Block SIGUSR1 in main thread using "pthread_sigmask(SIG_BLOCK, &blocked, NULL)"

Solution 2: Generate thread specific events using "sigev_notify = SIGEV_THREAD_ID". (Works for timers)

Thanks

他のヒント

Unlike most traditional system calls, clock_nanosleep does not return -1 on failure. According to the POSIX spec:

If the clock_nanosleep() function returns because it has been interrupted by a signal, it shall return the corresponding error value.

So try checking to see if it returns EINTR.

(Newer POSIX interfaces tend to return error codes instead of relying on errno. Somebody's idea of being more modern and thread-safe, I guess. Ultimate result is just a mess, though, IMO.)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top