开发者

Problem with signal/alarm in unix

The problem must be something pretty simple but..I can't figure out what it is. It should keep printing "alaarm" for some time, but it only does it once and then the program dies:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <signal.h>

void onAlarm();

void setupAlarm() {
 signal(SIGALRM, onAlarm);
 alarm(1);
}

void onAlarm() {
 setupAlarm();
 printf("alarmmmmmmmmmmmmmmmmm\n");
}

void main()
{
 setupAlarm();
 sleep(1000);
}

What might wrong in here? Taking out the sleep(1000) makes the program die instantaneously (that is, without showing even that one "alaaarm").

Answer

Ok, the following bit of code works:

void onAlarm() {
    printf("alarmmmmmmmmmmmmmmmmm\n");
    alarm(1);
    sleep(1);
}

void main()
{
    signal(SIGALRM, onAlarm);
    alarm(1开发者_JAVA百科);
    sleep(2);
}

but I am still wrapping my hand around this and trying to understand why I need to code it like this.


Oops, my previous answer was utterly wrong. Look into what happens when your onAlarm() is called:

  1. it resets the signal handler,

  2. it resets the alarm

  3. it starts waiting again having canceled the previous alarm.

What code path actually reaches your call of printf?


sleep() gets interrupted by a signal and errno is set to EINTR. i.e. after your first alarm, sleep() returns and your program exits as it reaches the end of main.

Note that you shouldn't call printf from a signal handler, printf is not signal async-safe.

There might be other gotchas as well, see here

I can't reproduce the behavior of your original code not printing anything, but if you want to know what's going on, simply run your program under strace or similar tools.


Well, for starters you tell your environment to generate a SIGALRM after a second, then exit after a second. Try increasing the wait to two seconds.


I don't know about your program, but this works for me (code taken from here) :

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

void catch_alarm (int sig);
void setupAlarm();

/* This flag controls termination of the main loop. */
volatile sig_atomic_t keep_going = 4;


/* The signal handler just clears the flag and re-enables itself. */
void catch_alarm (int sig) {
    keep_going--;
    printf("Alarm!!\n");

    if (keep_going) {
        setupAlarm();
    }
}

void setupAlarm() {
    alarm(1);
    sleep(1);
}

int main (int argc, char **argv) {
    signal(SIGALRM, catch_alarm);
    setupAlarm();

    return EXIT_SUCCESS;
}

This prints four Alarm! then exit.

You can replace your sleep(1); with a while (keep_going); in the main for the same result.

The problem is that alarm does not execute within your program's process id, therefore your program can end whether the alarm signal has been fired or not. However, sleep puts your program's process on hold for n seconds, then continue. Without some way to "pause" the process, or keep the process alive while waiting for the alarm, it will just die having executed everything that had to be executed. Even using a thread, without a sleep(), a while (...), etc. and a pthread_join(), the process will not wait for your alarm signal and just end (die). So you need to keep your process alive somehow while waiting for the signal to be fired, or else it will not work.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜