Interval Timer not firing signal at specified time interval - c

I want to call timer_handler function at every 2 seconds regardless of execution time of timer_handler function here is my code
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
void timer_handler (int signum)
{
static int count = 0;
sleep(1);
printf ("timer expired %d times %d signum \n", ++count, signum);
}
int main ()
{
struct sigaction sa;
struct itimerval timer;
/* 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 2000 msec... */
timer.it_value.tv_sec = 2;
timer.it_value.tv_usec = 0;
/* ... and every 2000 msec after that. */
timer.it_interval.tv_sec = 2;
timer.it_interval.tv_usec = 0;
/* Start a virtual timer. It counts down whenever this process is
executing. */
setitimer (ITIMER_VIRTUAL, &timer, NULL);
/* Do busy work. */
while (1);
}
As per above code it should print timer expired 1 times 26 signum at every two second but its prints on every 3 seconds which includes sleep time so i want to call that function on every 2 seconds.
I don't know where i am doing wrong
If any other library is able to do this please let me know
Thank you

Why not use wall-clock time?
To do so
install the signal handler for SIGALRM instead of SIGVTALRM and
specify ITIMER_REAL instead of ITIMER_VIRTUAL.
Unrelated but important: Signal handlers may only call async-signal-safe functions. printf() is not one of those. For a list of the latter click here and scroll down.

the call, in the signal handler: sleep(1) is adding an extra second to the processing of the signal. This extra second is not part of the execution time of the process.
remove from the signal handler:
sleep(1);
regarding:
setitimer (ITIMER_VIRTUAL, &timer, NULL);
since you want to see the signal handler executed every 2 seconds, the proper timer to use is: ITIMER_REAL not ITIMER_VIRTUAL. This will result in the 'clock on the wall' time being measured rather than the 'process run' time being measured.
Strongly suggest having the signal handler ONLY set a flag. Then the 'do nothing' loop in the main function be checking that flag, reset the flag, then call printf()` To properly accomplish this, with out an 'race' conditions, use a mutex/ Both the main and the signal handler would lock the mutex, modify the flag, then unlock the mutex.

Related

Linux C timer - signal disrupts current process

I'm working on a application that has specific timing restraints such that an event should occur (ideally exactly) every 200us. I'm trying to do this with a timer and signal.
#include <stdio.h>
#include <time.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
timer_t timer_id;
void start_timer(void)
{
struct itimerspec value;
value.it_value.tv_sec = 0;
value.it_value.tv_nsec = 20000;
value.it_interval.tv_sec = 0;
value.it_interval.tv_nsec = 200000;
timer_create(CLOCK_REALTIME, NULL, &timer_id);
timer_settime(timer_id, 0, &value, NULL);
}
void handler(int sig) {
printf("in handler\n");
}
void *my_thread(void *ignore)
{
(void)ignore;
start_timer();
// Sleep forever
while(1) sleep(1000);
}
int main()
{
pthread_t thread_id;
(void) signal(SIGALRM, handler);
pthread_create(&thread_id, NULL, my_thread, NULL);
// sleep is a placeholder for this SO question. I want to do
// other processing here
sleep(5000);
printf("sleep finished\n");
}
After 200us the signal handler is called. It appears to be called when the sleep(5000) line is running because the "sleep finished" message is displayed early. I want the timer to disrupt the thread that started the timer, not the main process. This is why I created a thread to start it. Is there a way to have the signal only abort the current instruction on the thread instead of on the main process? I know that the other threads/processes will be blocked when the handler runs, but I wanted them to continue afterwards as if nothing happened. For example, in this case I want to sleep at least 5000 seconds.
Yes, you can block the signal (pthread_sigmask) in the main thread before starting any other threads, and only unblock it in the thread intended to handle it. This will ensure that it arrives in the thread you want it in.
However, if you already have threads, are you sure you actually need a timer generating a signal for this? clock_nanosleep should allow sleep with wakeup at a precise time, and avoids all the awfulness of signals.

GDB, signals and SIG_IGN

Setting a signal handler as SIG_IGN ignores the signal while running the program normally but not while running it through gdb.
I'm creating a timer using timer_create and timer_settime functions. I don't want to use a signal handler (i.e a function) to handle the signals generated by this timer. I decided to use sigwait and wait for SIGALRM. I set the handler for SIGALRM as SIG_IGN and used sigwait.
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#define TRUE 1
#define ISTRUE(x) (x != 0)
#define bool int
int main() {
struct itimerspec timer_spec;
struct sigevent sig_event;
timer_t timer_id;
sigset_t sig_set;
timer_spec.it_interval.tv_sec = 1;
timer_spec.it_interval.tv_nsec = 0;
timer_spec.it_value.tv_sec = 1;
timer_spec.it_value.tv_nsec = 0;
sig_event.sigev_signo = SIGALRM;
sig_event.sigev_notify = SIGEV_SIGNAL;
signal(SIGINT, SIG_IGN);
signal(SIGALRM, SIG_IGN);
/* Create the timer */
timer_create(CLOCK_REALTIME, &sig_event, &timer_id);
timer_settime(timer_id, 0, &timer_spec, NULL);
sigemptyset(&sig_set);
sigaddset(&sig_set, SIGALRM);
int signal = 0;
bool running = TRUE;
while (ISTRUE(running)) {
sigwait(&sig_set, &signal);
switch(signal){
case SIGINT:
printf("Interrupt received.. exiting\n");
running = 0;
break;
case SIGALRM:
printf("Ticked\n");
break;
}
printf("Sleeping\n");
}
return 0;
}
While debugging the application in my IDE (CLion) as well as using gdb from the shell, the program functioned as expected. SIGALRM was not being ignored, which led me to believe that what I was doing was right. However, running the application normally, sigwait never returns.
I later realized that this was because the signal was being ignored and I needed to block the signal (using sigprocmask or similar) and set it to a pending state.
Why does, while debugging, the signal get passed through? Is this supposed to happen? What am I missing?
You should look into the handle gdb command:
(gdb) handle SIGALRM
Signal Stop Print Pass to program Description
SIGALRM No No Yes Alarm clock
(gdb) handle SIGALRM ignore
Signal Stop Print Pass to program Description
SIGALRM No No No Alarm clock
(gdb) help handle
... read it ;-) ...
As mentioned in the manpage of ptrace(2) (which gdb is using):
While being traced, the tracee will stop each time a signal is delivered, even if the signal is being ignored.

Catching SIGTERM, and sleep preventing it working

I have some code written in C (working on ubuntu 17):
void sig_stop(int sig_num) {
/* Some cleanup that needs to be done */
}
void some_routine(const char *array[], const int length) {
/* Initialization */
signal(SIGTERM, sig_stop);
while (true) {
/* Some function */
/* I have this sleep to minimize the load on the CPU
as I don't need to check the conditions here
all the time. */
sleep(5);
}
}
Whenever I include the 5 minute sleep (sleep(5)), it appears sig_stop isn't called. However, when I comment out the sleep(5), the sig_stop cleanup works just fine. Have I got something wrong with my understanding of how to catch SIGTERM?
If I can't use the sleep function, is there a better way to "sleep" the program" so that it only runs the loop every x minutes or in such a way that minimizes the CPU load?
sleep() and signals
sleep() should not prevent the signal from being caught and the signal handler being executed. From the manpage for sleep() (emphasis mine):
sleep() causes the calling thread to sleep either until the number of real-time seconds specified in seconds have elapsed or until a signal arrives which is not ignored.
Take the following example ...
#include <signal.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
static volatile sig_atomic_t flag = 0;
static void sig_stop(int signum) { flag = 1; }
int main(void) {
int secs_remaining = 0;
signal(SIGTERM, sig_stop);
while (!flag) {
printf("Sleeping at time %d\n", time(NULL));
secs_remaining = sleep(5);
}
printf(
"Flag raised. Exiting at time %d. sleep() was interrupted %d seconds "
"early ...\n",
time(NULL), secs_remaining);
return 0;
}
Note that - in the case where it was interrupted by a signal - sleep() returns the number of seconds left to sleep. E.g., if it is interrupted 3 seconds early it will return 3. It will return 0 if it is not interrupted.
Compile as gcc -o test test.c and run. Then from another terminal run
pkill -15 test
You will see output similar to the following ...
Sleeping at time 1532273709
Flag raised. Exiting at time 1532273711. sleep() was interrupted 2 seconds early ...
By the way ... sleep(x) sleeps for x seconds - not minutes.
signal() vs sigaction()
Due to portability issues associated with signal(), it is often recommended to use sigaction() instead. The use of sigaction() would be something like the following.
int main(void) {
struct sigaction sa;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sa.sa_handler = sig_stop;
if (sigaction(SIGTERM, &sa, NULL) == -1) {
perror("sigaction");
return 1;
}
// Etc.
}
As you can see the usage of sigaction() is a little more verbose than that of signal(). Perhaps that's why people still sometimes use signal().

how to set multiple Alarms using "setitimer()" function call

I have a requirement to set more than one interval-timers (alarms of same type : ITIMER_REAL) in the same process. so I used setitimer() system call to create 3 alarms with each timer having separate structures to hold time interval values. when any timer expires it will give a signal SIGALRM to the calling process, but i couldn't find which timer among three has given the signal and I don't even know whether all the timers are running or not. Is there any way to find which timer has given the signal...
Thank you.
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
void timer_handler (int signum)
{
static int count = 0;
printf ("timer1 expired %d times\n", ++count);
}
int main ()
{
int m = 0;
struct sigaction sa;
struct itimerval timer1, timer2, timer3;
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
sigaction (SIGALRM/*SIGVTALRM*/, &sa, NULL);
timer1.it_value.tv_sec = 1;
timer1.it_value.tv_usec = 0;
timer1.it_interval.tv_sec = 5;
timer1.it_interval.tv_usec = 0;
timer2.it_value.tv_sec = 2;
timer2.it_value.tv_usec = 0/* 900000*/;
timer2.it_interval.tv_sec = 5;
timer2.it_interval.tv_usec = 0/*900000*/;
timer3.it_value.tv_sec = 3;
timer3.it_value.tv_usec = 0/* 900000*/;
timer3.it_interval.tv_sec = 5;
timer3.it_interval.tv_usec = 0/*900000*/;
setitimer (ITIMER_REAL/*ITIMER_VIRTUAL*/, &timer1, NULL);
setitimer (ITIMER_REAL/*ITIMER_VIRTUAL*/, &timer2, NULL);
setitimer (ITIMER_REAL/*ITIMER_VIRTUAL*/, &timer3, NULL);
while (1)
{
//printf("\nin main %d",m++);
//sleep(1);
}
}
No, you only have one ITIMER_REAL timer per process. Using setitimer multiple times overwrites the previous value, see man setitimer
A process has only one of each of the three types of timers.
You can also see this, when you modify the intervals in your example code
timer1.it_interval.tv_sec = 1;
timer2.it_interval.tv_sec = 2;
and using nanosleep instead of sleep, because it might interfere with SIGALRM.
Now running the code, you will see only 5 second intervals.
You can also retrieve the previous set value by providing a second struct itimerval
struct itimerval old1, old2, old3;
setitimer(ITIMER_REAL, &timer1, &old1);
setitimer(ITIMER_REAL, &timer2, &old2);
setitimer(ITIMER_REAL, &timer3, &old3);
old1 will contain zero values, because it is the first time you use setitimer. old2 contains it_interval = 1 sec, and old3 contains it_interval = 2 sec. The it_values will be different, depending on how much time elapsed between the calls to setitimer.
So, if you need multiple timers, you need to do some bookkeeping. Each time a timer expires, you must calculate which timer is next and call setitimer accordingly.
As an alternative, you may look into POSIX timers. This allows to create multiple timers
A program may create multiple interval timers using timer_create().
and also pass some id to the handler via sigevent. Although the example at the end of the man page looks a bit more involved.
If I understand your question right you want to know the status of the different timers.
In the reference a getitimer function avalable:
The function getitimer() fills the structure pointed to by curr_value
with the current setting for the timer specified by which (one of
ITIMER_REAL, ITIMER_VIRTUAL, or ITIMER_PROF). The element it_value is
set to the amount of time remaining on the timer, or zero if the timer
is disabled. Similarly, it_interval is set to the reset value.
You can find the full reference here Link
Hope that helps

How can I resume execution of a function (not start it again) using swapcontext()?

I am building a pre-emptive userspace thread scheduler which uses a timer to interrupt threads and switch between them according to priority. However, once a thread is interrupted, I cannot seem to let it finish; only start it again. Is what I am asking for even possible using swapcontext? The result of this code, which should allow itake5seconds() to complete, just loops the "Hello" message over and over.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <ucontext.h>
static ucontext_t mainc, newthread;
void itake5seconds()
{
puts("Hello. I take 5 seconds to run.");
sleep(5);
puts("And I'm done! Wasn't that nice?");
}
void timer_handler(int signum)
{
puts("Doing some scheduler stuff.");
swapcontext(&mainc, &newthread);
}
int main(int argc, char* argv[])
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = &timer_handler;
sigaction(SIGALRM, &sa, NULL);
getcontext(&newthread);
newthread.uc_stack.ss_sp = malloc(5000);
newthread.uc_stack.ss_size = 5000;
newthread.uc_link = &mainc;
makecontext(&newthread, &itake5seconds, 0);
struct itimerval timer;
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 500000;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 500000;
setitimer(ITIMER_REAL, &timer, NULL);
while(1);
return 0;
}
Your code is calling an "unsafe" function in the signal handler (swapcontext). Therefor, the behavior of your program is "undefined".
From man 7 signal:
A signal handler function must be very careful, since processing elsewhere may be interrupted at some arbitrary point in the execution of the program. POSIX has the concept of "safe function". If a signal interrupts the execution of an unsafe function, and handler calls an unsafe function, then the behavior of the program is undefined.
See the "Example for SVID Context Handling" section in Complete Context Control for an example of how you can work this with a signal handler. But basically you'd use a volatile int global variable to flag that your signal handler was called and instead do the swapcontext call from normal code (i.e. code that's not running from within the context of signal handling).
The problem was that I was not saving the current execution context that swapcontext() returns to its first parameter.

Resources