So I'm trying to call an alarm to display a message "still working.." every second. I included signal.h.
Outside of my main I have my function: (I never declare/define s for int s)
void display_message(int s); //Function for alarm set up
void display_message(int s) {
printf("copyit: Still working...\n" );
alarm(1); //for every second
signal(SIGALRM, display_message);
}
Then, in my main
while(1)
{
signal(SIGALRM, display_message);
alarm(1); //Alarm signal every second.
That's in there as soon as the loop begins. But the program never outputs the 'still working...' message. What am I doing incorrectly? Thank you, ver much appreciated.
The
alarm()
call is for a one off signal.To repeat an alarm, you have to call
alarm()
again each time the signal occurs.However, the correct way to wait for the next
SIGALRM
is to use thepause()
function. Something the others have not mentioned (instead they have tight loops, ugly!)That being said, what you are trying to do would be much easier with a simple
sleep()
call as in:Note: The
sleep()
function is actually implemented using the same timer as thealarm()
and it is clearly mentioned that you should not mix both functions in the same code.(From Linux
man alarm
)You can create variations. For example, if you want the first message to happen after 1 second instead of immediately, move the
pause()
before theprintf()
.The "other work" comment supposes that your other work does not take more than 1 second.
It is possible to get the alarm signal on a specific thread if work is required in parallel, however, this can be complicated if any other timers are required (i.e. you can't easily share the
alarm()
timer with other functions.)P.S. as mentioned by others, doing your
printf()
inside the signal handler is not a good idea at all.There is another version where the
alarm()
is reset insidemain()
and the first message appears after one second and the loop runs for 60 seconds (1 minute):Note that with this method, the time when the message will be printed is going to be skewed. The time to print your message is added to the clock before you restart the alarm... so it is always going to be a little over 1 second between each call. The other loop is better in that respect but it still is skewed. For a perfect (much better) timer, the
poll()
function is much better as you can specify when to wake up next.poll()
can be used just and only with a timer. My Snap library uses that capability (look for therun()
function, near the bottom of the file.)There are also several Alarm and other signals code samples from the US Naval Academy.
Move the calls to
signal
andalarm
to just before your loop. Callingalarm
over and over at high speed keeps resetting the alarm to be in one second from that point, so you never reach the end of that second!For example:
Do not call
alarm()
twice, just call it once inmain()
to initiate the callback, then once indisplay_message()
. Try this code on Linux (Debian 7.8) :The result will be the following one :
Signal handlers are not supposed to contain "business logic" or make library calls such as
printf
. See C11 §7.1.4/4 and its footnote:All the signal handler should do is set a flag to be acted upon by non-interrupt code. This program runs correctly and does not risk crashing, even if some I/O other functionality were added:
Note, though, that spin loops are an awful way to program. This example uses 100% CPU power because it never sleeps. Furthermore
alarm
does not appear to be defined by the C standard although POSIX marks it as such and I recall it was part of K&R. So in terms of portability, you would be just as well off with another POSIX facility.ooga is correct that you keep reloading the alarm so that it will never go off. This works. I just put a
sleep
in here so you don't keep stepping on yourself in the loop but you might want to substitute something more useful depending on where you are headed with this.