0

I was trying POSIX timers togheter with POSIX signals handling. When I try to excecute the code you can find downhere, I get:

Errore timer_settime: Invalid argument

On GAPIL book, that is based upon Advanced Linux Programming and Unix network programming, I read that this can happen when inside new_value.value you specified a negative time value or a number of nanoseconds higher than 999999999. But I think that parameters I have used are okay...

#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/fcntl.h>
#include <sys/wait.h>
#include <stdbool.h>

void termination_handler(int signum)
{
    printf("Timer scaduto\n");
}

int main()
{
    timer_t timer1;
    struct sigevent sigeventStruct;
    sigeventStruct.sigev_notify = SIGEV_SIGNAL;
    sigeventStruct.sigev_signo = 10;
    if(timer_create(_POSIX_MONOTONIC_CLOCK, &sigeventStruct, &timer1) == -1)
    {
        printf( "Errore timer_create: %s\n", strerror( errno ) );
    }
    printf("timer_create eseguito\n");
    struct itimerspec tempoIniziale;
    tempoIniziale.it_value.tv_nsec = 0;

    struct itimerspec tempoFinale;
    tempoFinale.it_value.tv_nsec = 10000000;

    if(timer_settime(timer1, 0, &tempoIniziale, &tempoFinale) == -1)
    {
        printf( "Errore timer_settime: %s\n", strerror( errno ) );
    }





    struct sigaction newSigAzione, oldSigAzione;


    newSigAzione.sa_handler = termination_handler;
    //oldSigAzione.sa_handler = termination_handler;
    sigemptyset (&newSigAzione.sa_mask);

    newSigAzione.sa_flags = 0;


    sigaction (SIGEV_SIGNAL, NULL, &oldSigAzione);
    if(oldSigAzione.sa_handler != SIG_IGN)
    {
        //sigaction (SIGEV_SIGNAL, newSigAzione, NULL);
    }
    /*sigaction (SIGINT, NULL, &oldSigAzione);
    if (oldSigAzione.sa_handler != SIG_IGN)
      sigaction (SIGINT, &newSigAzione, NULL);
    sigaction (SIGHUP, NULL, &oldSigAzione);
    if (oldSigAzione.sa_handler != SIG_IGN)
      sigaction (SIGHUP, &newSigAzione, NULL);
    sigaction (SIGTERM, NULL, &oldSigAzione);
    if (oldSigAzione.sa_handler != SIG_IGN)
      sigaction (SIGTERM, &newSigAzione, NULL);*/

    /*sigaction (SIGTERM, &newSigAzione, NULL);*/

    return 0;
}
Germano Massullo
  • 2,572
  • 11
  • 40
  • 55
  • What is 10? What signal is that on your system? – jim mcnamara Jan 23 '12 at 14:33
  • It is an arbitrary number I setted to univocally identify the timer. This because in future I could use a lot of timers togheter – Germano Massullo Jan 23 '12 at 14:41
  • I think you should `exit()` if `timer_create()` fails. – Daniel Fischer Jan 23 '12 at 14:41
  • It doesn't look like you're initializing `tempoIniziale.it_value.tv_sec`. Perhaps you should do this? My man page says you can get `EINVAL` if "`new_value.it_value` is negative...", which means that either field of `new_value.it_value` is negative. – Dan Fego Jan 23 '12 at 14:42

1 Answers1

3

_POSIX_MONOTONIC_CLOCK is a feature test macro that tells you whether monotonic clocks are available on the system.

The available clock ids you can pass to timer_create() on Linux are:

CLOCK_REALTIME
  System-wide realtime clock. Setting this clock requires appropriate privileges.
CLOCK_MONOTONIC
  Clock that cannot be set and represents monotonic time since some unspecified starting point.
CLOCK_PROCESS_CPUTIME_ID
  High-resolution per-process timer from the CPU.
CLOCK_THREAD_CPUTIME_ID
  Thread-specific CPU-time clock.

You must also initialize all the members in struct sigevent and struct itimerspec. E.g. you don't set .tv_sec in the structitimer_spec, only .tv_nsec , which results in garbage values in those members.

...
memset(&sigeventStruct, 0, sizeof sigeventStruct);
...
and 
struct itimerspec tempoFinale;
memset(&tempoFinale, 0, sizeof tempoFinale);
tempoFinale.it_value.tv_nsec = 10000000;
nos
  • 223,662
  • 58
  • 417
  • 506