linux pthread running in a loop for specified time (avoiding signals) - c

hello what i want do is:
thread (pthread.h) need to execute code in a while loop for some period of time that will be defined at run time
after that the thread will finish correctly the last loop and continue for some other work.
right now I am using signals: This is the loop
setTimer(sec);
while(flag)
{
//do some work
}
// continue to run
and i use signal to call for function that will set flag to false:
void setTimer(int sec)
{
struct sigaction sa;
struct itimerval timer;
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &alarm_end_of_loop; // this is the function to change flag to false
sigaction (SIGVTALRM, &sa, NULL);
timer.it_value.tv_sec = sec;
timer.it_value.tv_usec = 0;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
setitimer (ITIMER_REAL, &timer, NULL);
}
void alarm_end_of_loop()
{
flag = 0; //flag is global but only one thread will access it
}
My question is there a way to avoid using signals?

Seems to be a timeout pattern.
double get_delta_time_to_now(const time_t timeout_time)
{
time_t now;
time(&now);
return difftime(now, timeout_time);
}
void do_it(int sec)
{
time_t timeout_time;
double diff;
time(&timeout_time);
timeout_time += sec; /* this is not necessarily correct */
diff = get_delta_time_to_now(timeout_time);
while (diff <= 0.0)
{
/* do your stuff */
diff = get_delta_time_to_now(timeout_time);
}
}

Related

Understanding struct itimerval field tv_usec

Hi I'm studying this code:
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
volatile sig_atomic_t print_flag = true;
static int count = 0;
void timer_handler (int signum)
{
printf ("timer expired %d times\n", ++count);
if(count>20) {
print_flag = false;
}
}
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 (print_flag) {
sleep(1);
}
printf("job done bye bye\n");
exit(0);
}
With this settings everything goes fine and i get this output
...
timer expired 17 times
timer expired 18 times
timer expired 19 times
timer expired 20 times
timer expired 21 times
job done bye bye
If i try to alter the code commenting timer.it_interval.tv_usec and timer.it_interval.tv_usecand setting both timer.it_value.tv_sec and timer.it_value.tv_sec equal to, for instance, 3 it doesn't do his job.
However if I maintain an explicit declaration of tv_usec like this it works:
timer.it_value.tv_sec = 3;
timer.it_value.tv_usec = 0;
timer.it_interval.tv_sec = 3;
timer.it_interval.tv_usec = 0;
Why I'm bonded on the explicit declaration of tv_usec for both fields?
As far as you don't initialize *.tv_usec fields, theirs values are undefined. If it'd contain a value greater that 999999 or less than 0, the setitimer () will just fail with EINVAL as described on the man page.
You ought to initialize all the data yourself. If you are willing to save a line of code, you may memset the timer struct to 0 the same way you have done it for sa.

How to generate same signal (SIGALRM) again and again?

We are trying to take control from while(1) loop in three of our functions using sigaction and setitimer and problem that we are facing right now is that only once SIGALRM is generated and for the next time it is not generating ie we are able to take control from while(1) of fun1() but not from while(1) of fun2().
Could you please suggest the ways to over come this problem.Please find the code below.
#define INTERVAL 500
void fun1();
void fun2();
void fun3();
void timer_handler(int );
struct itimerval it_val;
int count=0;
void timer_handler (int signum)
{
L1:
printf(“\nScheduler Called .. Calling Fun1″);
if(count==0){
count++;
fun1();
}
printf(“\nScheduler Called .. Calling Fun2″);
if(count==1){
count++;
fun2();
}
printf(“\nScheduler Called .. Calling Fun3″);
if(count==2){
count++;
fun3();
}
count=0;
goto L1;
}
void fun1()
{
struct sigaction sa;
/* Install timer_handler as the signal handler for SIGVTALRM. */
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
/* Configure the timer to expire */
it_val.it_value.tv_sec = INTERVAL/1000;
it_val.it_value.tv_usec = (INTERVAL*1000) % 1000000;
it_val.it_interval.tv_sec = INTERVAL/1000;;
it_val.it_interval.tv_usec=(INTERVAL*1000) % 1000000;
/* Start a timer. It counts down whenever this process is*/
sigaction (SIGALRM, &sa, NULL);
setitimer (ITIMER_REAL, &it_val, NULL);
while (1){
printf(“\nfun1″);
}
}
void fun2()
{
struct sigaction sa;
/* Install timer_handler as the signal handler for SIGVTALRM. */
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
/* Configure the timer to expire */
it_val.it_value.tv_sec = INTERVAL/1000;
it_val.it_value.tv_usec = (INTERVAL*1000) % 1000000;
it_val.it_interval.tv_sec = INTERVAL/1000;;
it_val.it_interval.tv_usec=(INTERVAL*1000) % 1000000;
/* Start a timer. It counts down whenever this process is*/
sigaction (SIGALRM, &sa, NULL);
setitimer (ITIMER_REAL, &it_val, NULL);
while (1){
printf(“\nfun2″);
}
}
void fun3()
{
struct sigaction sa;
/* Install timer_handler as the signal handler for SIGVTALRM. */
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
/* Configure the timer to expire */
it_val.it_value.tv_sec = INTERVAL/1000;
it_val.it_value.tv_usec = (INTERVAL*1000) % 1000000;
it_val.it_interval.tv_sec = INTERVAL/1000;;
it_val.it_interval.tv_usec=(INTERVAL*1000) % 1000000;
/* Start a timer. It counts down whenever this process is*/
sigaction (SIGALRM, &sa, NULL);
setitimer (ITIMER_REAL, &it_val, NULL);
while (1){
printf(“\nfun3″);
}
}
int main(){
timer_handler(1);
return 0;
}
When a signal is delivered it is automagically masked until the action function returns.
In general you want to your signal action function to do the absolute minimum. What you have written is effectively a recursive action function with most of your program inside it. Even if it did work you would be eating stack until there was none left !
Chapter and verse: from sigaction() for POSIX:
When a signal is caught by a signal-catching function installed by
sigaction(), a new signal mask is calculated and installed for the
duration of the signal-catching function (or until a call to either
sigprocmask() or sigsuspend() is made). This mask is formed by taking
the union of the current signal mask and the value of the sa_mask for
the signal being delivered, and unless SA_NODEFER or SA_RESETHAND is
set, then including the signal being delivered. If and when the user's
signal handler returns normally, the original signal mask is restored.
Read carefully time(7) and signal(7) and signal-safety(7)
A signal handler can do very few things (it should not call, even indirectly, printf or malloc ...) Many signal handlers simply set a volatile sigatomic_t integer variable, which is later tested in the code.
I would suggest having some event loop based upon some multiplexing syscall like poll(2). You could use existing event loop frameworks (like libev, libevent, glib, etc....) or make your own above poll. The Linux specific timerfd_create(2) & signalfd(2) could help a lot.

Is there any method to wait until task catch SIGALRM signal in intel arch?

I'm programming iwth gcc version 4.4.3 on Ubuntu 10.04
I don't know how to catch SIGALRM with sigtimedwait(),sigwait().
If timer handler is set , sigtimedwait(),sigwait() always returns EINTR(4).
If timer handler is not set, SIGALRM never received.
Is there any method to wait until task catch SIGALRM signal in intel arch?
void handler( int signo )
{
...
}
int main( void )
{
timer_t timer_id;
struct sigaction sigact;
struct itimerspec itval;
int ret;
struct timespec pTimeout;
siginfo_t pInfo;
pTimeout.tv_sec = 10;
pTimeout.tv_nsec = 0;
// set signal handler for SIGALRM
sigact.sa_handler = handler;
sigact.sa_flags = 0;
sigemptyset( &sigact.sa_mask );
sigaction( SIGALRM, &sigact, NULL );
// create timer
timer_create( CLOCK_REALTIME, NULL, &timer_id );
itval.it_value.tv_sec = 3;
itval.it_value.tv_nsec = 0;
itval.it_interval.tv_sec = 0;
itval.it_interval.tv_nsec = 250 * 1000 * 1000;
// set timer
timer_settime( timer_id, 0, &itval, NULL );
int count;
for ( count = 0; count < 10; count++ )
{
// wait for SIGALRM
ret = sigtimedwait
(
&sigact.sa_mask, /* the signal mask while suspended */
&pInfo, /* return value */
&pTimeout
);
.....
}
Is this helpful?
do {
ret = sigtimedwait(&sigact.sa_mask, &pInfo, &pTimeout);
} while (ret < 0 && errno == EINTR);
Similar question.
Some of the 'wait until a signal is received' functions are:
pause()
sigsuspend()
sigpause()
The sigpause() function is actually part of a deprecated set of functions; it is best not to use it in new code.
There is also:
sigtimedwait()
which may do what you want more directly.

How do I restart timer?

I use the following code to set an alarm.
struct itimerval timer;
struct sigaction sa;
sa.sa_handler = handler;
sa.sa_flags = SA_RESETHAND;
timer.it_value.tv_usec = 0;
timer.it_value.tv_sec = 1;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
sigaction(SIGALRM, &sa, 0);
setitimer(ITIMER_REAL, &timer, 0);
How do I restart the timer after it has exited the handler function and went into the while loop below. Do I need to reinitialize everything or just call setittimer?
while(pause() == -1)
{
// goes in here after handler function.. what needs to go here to restart timer?
}
Singe you use SA_RESETHAND you need to call both sigaction and setitimer again. I suggest you put it in a function so you don't have to write the code to start (or restart) the timer twice or more.

need programs that illustrate use of settimer and alarm functions in GNU C

Can anyone illustrate the use of settimer or alarm function in gnu C , with some program examples ,please ?
I have a program that continuously processes some data , and i need to set a timer / alarm that goes off every t seconds , in response to which , i need to store the processed data into a file. This file writing has to be asynchronous < i.e. the data processing and file writing must not wait for each other > . I went through the GNU C Library pages , but i couldn't understand much..
[EDIT]
I got this program :
#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
#define INTERVAL 1
int howmany = 0;
void alarm_wakeup (int i)
{
struct itimerval tout_val;
signal(SIGALRM,alarm_wakeup);
howmany += INTERVAL;
printf("\n%d sec up partner, Wakeup!!!\n",howmany);
tout_val.it_interval.tv_sec = 0;
tout_val.it_interval.tv_usec = 0;
tout_val.it_value.tv_sec = INTERVAL; /* 10 seconds timer */
tout_val.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &tout_val,0);
}
void exit_func (int i)
{
signal(SIGINT,exit_func);
printf("\nBye Bye!!!\n");
exit(0);
}
int main ()
{
struct itimerval tout_val;
tout_val.it_interval.tv_sec = 0;
tout_val.it_interval.tv_usec = 0;
tout_val.it_value.tv_sec = INTERVAL; /* 10 seconds timer */
tout_val.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &tout_val,0);
signal(SIGALRM,alarm_wakeup); /* set the Alarm signal capture */
signal(SIGINT,exit_func);
while (1)
{
//printf("!");
}
return 0;
}
But seems like i cannot do anything while the timer is on..
What should i modify to suit my needs ? Pl suggest..
[/EDIT]
Here's an example from here which uses setitimer() to periodically call DoStuff().
The key here is that calling setitimer() results in the OS scheduling a SIGALRM to be sent to your process after the specified time has elapsed, and it is up to your program to handle that signal when it comes. You handle the signal by registering a signal handler function for the signal type (DoStufF() in this case) after which the OS will know to call that function when the timer expires.
You can read the setitimer() man page to figure out what the arguments are and how to cancel a timer.
Note: if you want the timer to trigger only once, you will have to call alarm() or ualarm() instead of setitimer().
/*
* setitimer.c - simple use of the interval timer
*/
#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(void);
int main(int argc, char *argv[]) {
struct itimerval it_val; /* for setting itimer */
/* Upon SIGALRM, call DoStuff().
* Set interval timer. We want frequency in ms,
* but the setitimer call needs seconds and useconds. */
if (signal(SIGALRM, (void (*)(int)) DoStuff) == SIG_ERR) {
perror("Unable to catch SIGALRM");
exit(1);
}
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) {
perror("error calling setitimer()");
exit(1);
}
while (1)
pause();
}
/*
* DoStuff
*/
void DoStuff(void) {
printf("Timer went off.\n");
}

Resources