Sigaction and SIGALRM - c

Hi I'm trying to learn more about signals and I wrote a simple code that supposed to just print "bye" everything the alarm signal is send. I am using sigaction to set this. However, I keep returning NULL in my error checking could someone tell me what I'm doing wrong. Thanks in Advance!
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/time.h> /* for setitimer */
#include <unistd.h> /* for pause */
#include <signal.h> /* for signal */
#define INTERVAL 500 /* number of milliseconds to go off */
/* function prototype */
void DoStuff();
int main(int argc, char *argv[]) {
struct itimerval it_val; /* for setting itimer */
struct sigaction sa;
sa.sa_handler = &DoStuff;
/* Upon SIGALRM, call DoStuff().
* Set interval timer. We want frequency in ms,
* but the setitimer call needs seconds and useconds. */
if (sigaction(SIGALRM,&sa,NULL) < 0) { /*set the signal to be enabled if this action occurs*/
perror("Unable to catch SIGALRM");
exit(1);
}
it_val.it_interval = it_val.it_value;
it_val.it_value.tv_sec = INTERVAL/1000;
it_val.it_value.tv_usec = (INTERVAL*1000) % 1000000;
it_val.it_interval = it_val.it_value;
if (setitimer(ITIMER_REAL, &it_val, NULL) == -1) { /*set the timer to send the alarm command*/
perror("error calling setitimer()");
exit(1);
}
while(1)
{
pause();
}
}
void DoStuff() {
printf("bye\n");
}

sigaction cannot return null, since it returns an integer. I'm assuming it's returning -1. You're not correctly initializing the sigaction structure. It has many fields, but you're allowing them to be undefined. Fix the structure definition and try again. See:
http://man7.org/linux/man-pages/man2/sigaction.2.html

Related

reading a line from stdin until a signal is sent

I want to write some code that takes input from stdin, and prints the input on the next line, until a signal is sent, the signal being SIGINT in this case. So far I have this code which just prints a message when SIGINT is sent:
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <stdbool.h>
#include <time.h>
bool signalSent = false;
void flag(int signal) {
signalSent = true;
}
int main(int argc, char** argv) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = flag;
sa.sa_flags = SA_RESTART;
sigaction(SIGINT, &sa, 0);
while (true) {
while (!signalSent) {
usleep(500000);
}
printf("signal sent\n");
signalSent = false;
}
return 0;
}
I tried using fgets() to get the input from stdin and print to stdout, but when I enter ^C (SIGINT) I have to press enter, but I want it to send the message ("signal sent\n"); as soon as it is pressed like the code I currently have. Code using fgets():
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <stdbool.h>
#include <time.h>
bool signalSent = false;
void flag(int signal) {
signalSent = true;
}
int main(int argc, char** argv) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = flag;
sa.sa_flags = SA_RESTART;
sigaction(SIGINT, &sa, 0);
while (true) {
while (!signalSent) {
char buffer[80];
char* t = fgets(buffer, sizeof(buffer), stdin);
printf("%s", t);
fflush(stdout);
}
printf("signal sent\n");
signalSent = false;
}
return 0;
}
Output from code:
For reference I want my output to look like the picture below. Im very new to using signals in C as well.
As detailed in the manual pages for sigaction(2) and signal(7), the SA_RESTART flag causes certain system calls, including read(2), to automatically restart after the signal handler has ended.
It seems that you do not want this behaviour.
fgets is implemented by way of read, and can fail for the same reasons it can. Without SA_RESTART, while waiting on input from a "slow" device (this includes terminals), these functions will set errno to EINTR if interrupted by a signal.
Note that what can and cannot be done in a signal handler is complicated.
Consider using sig_atomic_t objects, declared as volatile, for these types of flags.
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
static volatile sig_atomic_t signal_sent = 0;
void flag(int signal) {
(void) signal;
signal_sent = 1;
}
int main(void) {
struct sigaction sa = { .sa_handler = flag };
sigaction(SIGINT, &sa, 0);
while (!signal_sent) {
char buffer[80];
if (fgets(buffer, sizeof buffer, stdin))
printf("%s", buffer);
else if (errno == EINTR && signal_sent) {
puts("signal sent");
signal_sent = 0;
} else
return 1;
}
}
Example of running this program (^D to terminate):
$ ./a.out
foo
foo
^Csignal sent
^Csignal sent
bar
bar
hello wor^Csignal sent

Understanding output of program

I was looking at this stack exchange question: how to call a function automatically at regular intervals?
And I tried running the code in the first answer
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
void timer_handler (int signum)
{
static int count = 0;
printf ("timer expired %d times\n", ++count);
}
int main ()
{
struct sigaction sa;
struct itimerval timer;
/* Install timer_handler as the signal handler for SIGVTALRM. */
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
sigaction (SIGVTALRM, &sa, NULL);
/* Configure the timer to expire after 250 msec... */
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 250000;
/* ... and every 250 msec after that. */
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 250000;
/* Start a virtual timer. It counts down whenever this process is
executing. */
setitimer (ITIMER_REAL, &timer, NULL);
/* Do busy work. */
while (1);
}
I don't understand what it is doing. It appears to print "Alarm Clock" after 2500 milliseconds, but I don't understand how that's possible since there is no print statement to that effect. How do I get it to increment the counter every 2500 milliseconds like its supposed to?
ITIMER_REAL sends SIGALRM not SIGVTALRM.
Change the signal and it'll work.
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
void timer_handler (int signum)
{
static int count = 0;
printf ("timer expired %d times\n", ++count);
}
int main ()
{
struct sigaction sa;
struct itimerval timer;
/* Install timer_handler as the signal handler for SIGVTALRM. */
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
sigaction (SIGALRM, &sa, NULL);
/* Configure the timer to expire after 250 msec... */
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 250000;
/* ... and every 250 msec after that. */
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 250000;
/* Start a virtual timer. It counts down whenever this process is
executing. */
setitimer (ITIMER_REAL, &timer, NULL);
/* Do busy work. */
while (1);
}
(Generally, it's a bad idea to printf in a signal handler since printf isn't async-signal safe, but in your case it shouldn't be dangerous, because you're interrupting regular-context code that is async-signal safe (namely the busy loop). POSIX doesn't appear to guarantee this special exception, though, so to be perfectly safe, you should refrain from making any async-signal unsafe calls in signal handlers and replace the printf with a write(1, ...).)

timer_create() not able to catch a signal in handler function

Here i am trying achieve a timer say 0-10secs and an interval of 2secs each,so that i need to generate an interrupt # every 2secs(total 5 times) saying 2secs completed. which i have been cross checking in handler() function by using printf(). But i am not able to achieve the desired result.please put me touch if anyone is aware of it.
Thanks in advance.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#define SIGTIMER (SIGRTMAX)
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)
void handler(int sig, siginfo_t *si, void *uc)
{
printf("Caught signal %d\n", sig);
}
int
main(int argc, char *argv[])
{
timer_t timerid;
struct sigevent sev;
struct itimerspec its;
struct itimerspec oitval;
struct sigaction sa;
/* Establish handler for timer signal */
printf("Establishing handler for signal %d\n", SIGTIMER);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGTIMER, &sa, NULL) == -1)
errExit("sigaction");
/* Create the timer */
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGTIMER;
sev.sigev_value.sival_ptr = &timerid;
if (timer_create(CLOCK_REALTIME, &sev, &timerid) == 0)
{
printf("timer ID is 0x%lx\n", (long) timerid);
/* Start the timer */
its.it_value.tv_sec = 10;
its.it_value.tv_nsec =0;
its.it_interval.tv_sec = 2;
its.it_interval.tv_nsec = 0;
if (timer_settime(timerid, 0, &its, &oitval) == -1)
errExit("timer_settime");
}
else
{
errExit("timer_create");
}
return 0;
}
First of all you should properly setup timeouts:
/* Start the timer */
its.it_value.tv_sec = 2;
its.it_value.tv_nsec = 0;
its.it_interval.tv_sec = 2;
its.it_interval.tv_nsec = 0;
it_value is the duration before first triggering, and it_interval is time between all subsequent triggerings. See here. Then, you shouldn't return from main() due it leads to process exit and you won't be able to observe timer ticks. You need to block execution somehow, e.g.
while(1) sleep(INT_MAX);
After each tick sleep() returns with errno set to EINTR so it should we wrapped into loop to allow timer to go ahead. Later you can decide when to leave this loop and exit.
P.S. Using printf() from signal handler is not a good idea. You should be very carefully with what you are doing there. It would be better just to write to some global variable and immediately return. And that var may be tested immediately after sleep() giving you an idea if you should sleep again or return.

Timer freezes after some time

I am running the following program which implements a timer. When a thread awake after receiving a signal on condition variable from the previous running thread, it creates a timer and send a signal to the next thread on timer expiration. I want it to run for some time, but the timer stops ticking after some runs.
//Import
#define _POSIX_C_SOURCE 199309
#include <sched.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#define NUM_THREADS 10
#define CLOCKID CLOCK_REALTIME
#define SIG SIGUSR1
timer_t timerid;
pthread_cond_t condA[NUM_THREADS+1] = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_t tid[NUM_THREADS];
int state = 0;
static void handler(int sig, siginfo_t *si, void *uc)
{
if(si->si_value.sival_ptr != &timerid){
printf("Stray signal\n");
} else {
//printf("Caught signal %d from timer\n", sig);
}
pthread_cond_signal(&condA[state]);
}
void *threadA(void *data_)
{
int i = 0, s;
long int loopNum, j;
int turn = (intptr_t)data_;
struct timeval tval_result;
// Timer's part starts
struct sigevent sev;
struct itimerspec its;
long long freq_nanosecs;
sigset_t mask;
struct sigaction sa;
// TImer'spart ends
while(1)
{
/* Wait for state A */
pthread_mutex_lock(&mutex);
for (;state != turn;)
{
s = pthread_cond_wait(&condA[turn], &mutex);
if (s != 0)
perror("pthread_cond_wait");
// printf("main(): state = %d\n", state);
}
pthread_mutex_unlock(&mutex);
//do stuff
for(j=0;j<10000;j++)
{//some dummy time consuming works}
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
sigaction(SIG, &sa, NULL);
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIG;
sev.sigev_value.sival_ptr = &timerid;
timer_create(CLOCKID, &sev, &timerid);
/* Start the timer */
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = 2000;
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
timer_settime(timerid, 0, &its, NULL);
pthread_mutex_lock(&mutex);
state = (state +1)%NUM_THREADS;
//pthread_cond_signal(&condA[state]);
pthread_mutex_unlock(&mutex);
// Timer's code ends
}
}
int main(int argc, char *argv[])
{
int data = 0;
int err;
while(data < NUM_THREADS)
{
//create our threads
err = pthread_create(&tid[data], NULL, threadA, (void *)(intptr_t)data);
if(err != 0)
printf("\ncan't create thread :[%s]", strerror(err));
else
// printf("\n Thread created successfully\n");
data++;
}
pthread_exit(NULL);
}
Although no printf statements are executing, why is it freezing after some time?
If no. of timers are limited, what other strategy should I use to redress this issue?
POSIX says:
It is not safe to use the pthread_cond_signal() function in a signal handler that is invoked asynchronously.
Most likely you end up corrupting the state of pthread_cond_wait/pthread_cond_signal and anything can happen.
Don't mix threads and signal handlers, it leads only to madness. There are very few things you're allowed to do inside a signal handler, even fewer that are thread related, it's very hard to ensure that the right thread ends up handling the right signal, etc.
If you're doing threads anyway implement a timer in one thread that calculates how much time it needs to sleep to deliver the next event (don't just hardcode it to your timer period since that will make your timer drift), sleep that much and call pthread_cond_signal.
Also, it's bad form to have naked pthread_cond_signal calls and most often a bug. You might get unlucky and call it just before the other thread does the pthread_cond_wait and your signal will get lost. The normal thing to do is to set a variable (protected by a mutex, that's why pthread_cond_signal wants a mutex) and then signal that the variable is set.
If you think this is too much work, condition variables are probably not the right mechanism in this case and you should use semaphores instead. Incidentally sem_post is legal to call from a signal handler according to POSIX, but I still think it's a bad idea to mix threads with signals.

Signal Handler to stop Timer in C

I am trying to have a signal handler stop a timer without exiting my program. How should I go about. I want StopTimer to handle the signal to stop the timer
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>
#define INTERVAL 2 // number of seconds to go off
int main(int argc, char* argv[]) {
TimerSet(INTERVAL);
while(1)
{
// do stuff
}
return 0;
}
void TimerSet(int interval)
{
printf("starting timer\n");
struct itimerval it_val;
// interval value
it_val.it_value.tv_sec = interval;
it_val.it_interval = it_val.it_value;
// on SIGALRM, close window
if (signal(SIGALRM, TimerStop) == SIG_ERR)
{
perror("Unable to catch SIGALRM");
exit(1);
}
// set interval timer, returns SIGALRM on expiration
if (setitimer(ITIMER_REAL, &it_val, NULL) == -1)
{
perror("error calling setitimer()");
exit(1);
}
}
void TimerStop(int signum)
{
printf("Timer ran out! Stopping timer\n");
exit(signum);
}
I tried to set the setitimer interval to 0, but I am not sure how to use the same timer within the TimerStop signal handler function
Just set it_interval to zero, and you'll get a one-shot timer. You don't need to do anything with it in your handler.
For instance, with this:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>
#define INTERVAL 2 // number of seconds to go off
void TimerStop(int signum) {
printf("Timer ran out! Stopping timer\n");
}
void TimerSet(int interval) {
printf("starting timer\n");
struct itimerval it_val;
it_val.it_value.tv_sec = interval;
it_val.it_value.tv_usec = 0;
it_val.it_interval.tv_sec = 0;
it_val.it_interval.tv_usec = 0;
if (signal(SIGALRM, TimerStop) == SIG_ERR) {
perror("Unable to catch SIGALRM");
exit(1);
}
if (setitimer(ITIMER_REAL, &it_val, NULL) == -1) {
perror("error calling setitimer()");
exit(1);
}
}
int main(int argc, char *argv[]) {
TimerSet(INTERVAL);
while (1) {
// do stuff
}
return 0;
}
the message "Timer ran out! Stopping timer" will appear only once, and your timer will stop without you doing anything.
Note that you need to fill in the tv_usec members of your struct itimerval, which your current code does not do. If you don't, it_interval is highly unlikely to be zero, and your timer will never stop.
printf(), along with the other standard IO functions, is not really safe to call from a signal handler, although in this particular case it won't cause you any problems, since the main code is just sitting in a loop and not doing anything.
Also, presume you're calling signal() on purpose - sigaction() is the recommended way for setting handlers. setitimer() is also obsolete, now, and timer_settime() is recommended.
According to manual:
Timers decrement from it_value to zero, generate a signal, and reset to
it_interval. A timer which is set to zero (it_value is zero or the timer
expires and it_interval is zero) stops.
Both tv_sec and tv_usec are significant in determining the duration of a
timer.
So timer can be set to run only once if interval is set to zero before setitimer() call (thanks to Duck's comment).

Resources