Search code examples
ctimerposix

SIGEVENT sival_ptr Segmentation fault


Im trying to pass a pointer to the timer handler using sigevent and then printing it using write(). I am unable to unreference it in the timer handler. See below the comments:

#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>

static void timerHandler( int sig, siginfo_t *si, void *uc )
{

    char * c;
    c = (char *) si->si_value.sival_ptr;
    write(1,c,1);  /* Prints nothing */

    char h = (char) 'x';    
    write(1,&h,1); /*   Prints ok    */

    char f = (char) *c;
    write(1,&f,1); /* Segmentation Fault */

}

int main(void)
{

    static char a = 'k';
    write(1,(char *) &a,1); /* Prints ok */

    struct sigevent te;
    struct itimerspec its;
    struct sigaction sa; 
    timer_t timerID;
    int sigNo = SIGRTMIN;

    /* Set up signal handler. */
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = timerHandler;
    sigemptyset(&sa.sa_mask);
    if (sigaction(sigNo, &sa, NULL) == -1) {
        perror("sigaction");
    }

    /* Set and enable alarm */
    te.sigev_notify = SIGEV_SIGNAL;
    te.sigev_signo = sigNo;
    te.sigev_value.sival_ptr = &a;
    te.sigev_value.sival_int = 5;
    timer_create(CLOCK_REALTIME, &te, &timerID);

    /* One Second Interval */
    its.it_interval.tv_sec = 1;
    its.it_interval.tv_nsec = 0;
    its.it_value.tv_sec = 1;
    its.it_value.tv_nsec = 0;
    timer_settime(timerID, 0, &its, NULL);

    while(1);;
}

What am I doing Wrong ? I'm compiling with: /usr/bin/gcc-5 main.c -o main -lrt


Solution

  • sigev_value is a union:

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

    You can use either sival_ptr or sival_int but not both.

    To fix, remove the following line:

    te.sigev_value.sival_int = 5;