Problem with signal handler and interrupted system call

Hi,

I have a daq program that runs in an infinite loop until it receives SIGINT. A handler catches the signal and sets a flag to stop the while loop. After the loop some things have to be cleaned up.
The problem is that I want my main while loop to wait until the next full second begins, to start some action. To do so it waits for the RTC interrupt. Unfortunately the read() which waits for the interrupt seems to be interrupted itself by SIGINT. That causes my program to exit abnormally with

read: Interrupted system call

and without cleaning up.
I already tried it with SIGHUP and SIGUSR1 instead of SIGINT without succes.

How could I prevent my read() from being interrupted?

Thanks in advance

Here are the important code snippets:
the loop in main()

    /* 
     * Signal handling 
     */ 
    struct sigaction act;
    /* define the signal action */
    act.sa_handler = terminate;
    /* make "act" an empty signal set */
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    /* instead of SIGHUP do "act" */
    sigaction(SIGHUP, &act, 0);
    
    /* 
     * main loop : runs until the signal handler  
     * receives a SIGINT to change "keep_running" to 0
     */
    while(keep_running){
        /* wait for irq */
        retval = await_rtc_irq(freq);
        /*.....*/
    }
    syslog (LOG_NOTICE, "clean up and exit\n");
    close(fdlock);
    unlink(DAQD_LOCK_FILE);
    closelog();
    return 0;

the wait_for_the_interrupt function

long int await_rtc_irq(int freq)
{
    int fd;
    long int retval, controlval;
    unsigned long data;
    
    /* open the RTC IRQ */
    fd = open ("/dev/rtc", O_RDONLY);
    
    if (freq == 1) {
        /* Enable periodic 1Hz interrupts */
        retval = ioctl(fd, RTC_UIE_ON, 0);
        if (retval == -1) {
            perror("ioctl");
            exit(errno);
        }
        /* call the read function to await the Alarm interrupt */
        retval = read(fd, &data, sizeof(unsigned long));
        if (retval == -1) {
            perror("read");
            exit(errno);
        }
        controlval = retval;
        /* Turn off update interrupts */
        retval = ioctl(fd, RTC_UIE_OFF, 0);
        if (retval == -1) {
            perror("RTC_UIE_OFF ioctl");
            exit(errno);
        }    
    }
    /* For frequencies different from 1 the irq has to be set differently.*/
    else if (freq == 2 || freq == 4 || freq == 8 || freq == 16 || 
         freq == 32 ||   freq == 64|| freq ==128){
        /* set peridoc interrupt frequncy */
        retval = ioctl(fd, RTC_IRQP_SET, freq);
        if (retval == -1) {
            perror("ioctl");
            exit(errno);
        }
        /* Enable periodic interrupts */
        retval = ioctl(fd, RTC_PIE_ON, 0);
        if (retval == -1) {
            perror("ioctl");
            exit(errno);
        }
        /* call the read function to await the Alarm interrupt */
        retval = read(fd, &data, sizeof(unsigned long));
        if (retval == -1) {
            perror("read");
            exit(errno);
        }
        controlval = retval;
        /* Disable periodic interrupts */
        retval = ioctl(fd, RTC_PIE_OFF, 0);
        if (retval == -1) {
            perror("RTC_PIE_OFF ioctl");
            exit(errno);
        }
    }
    else {
        puts("frequency not supported");
        exit(1);
    }
    close(fd);
    return(controlval);
}

That's your problem, more or less. If read() is interrupted by a system call, it returns -1, sets errno to EINTR. Your program itself does the perror and exiting, not read(). So just check if the return is -1 and errno != EINTR and restart the loop (for instance). You'll have to handle the logic for the ioctls and what not, too, or every now and then, your signal will interrupt the ioctl and exit.

That did it.
I totally missed to consider and change the error handling for the ioctls...

Thanks from Garmisch to Tirol