Actually I want to implement non-blocking timer, when the timer expires a handler will be called and will do something (for now it prints data). I google and realized that timer_create, timer_settimer are non-blocking timer. BUT still I've issue, I have to wait for my timer to expire (sleep(MAX) or while(1) {;}). But then if I'm calling my start_timer method with different "expiry" time, it should work accordingly, should not block other. e.g. here first time I'm calling timer, and expecting to call handler in 5 sec but before that 2nd call should print its data as, that interval I've given is 1sec only. And of course its not behaving same. Any idea?
#include <time.h>
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
typedef struct _data{
char *name;
}data;
void handler(union sigval val)
{
data *data_handler = val.sival_ptr;
printf("Handler entered with value :%s\n", data_handler->name);
}
void mod_timer(timer_t timerid, struct sigevent sig, struct itimerspec in, struct itimerspec out)
{
printf("mod_timer\n");
timer_settime(timerid, 0, &in, &out);
while(1)
sleep(1);
//delete the timer.
timer_delete(timerid);
}
void start_timer(void* val, int interval)
{
int Ret;
pthread_attr_t attr;
pthread_attr_init( &attr );
struct sched_param parm;
parm.sched_priority = 255;
pthread_attr_setschedparam(&attr, &parm);
struct sigevent sig;
sig.sigev_notify = SIGEV_THREAD;
sig.sigev_notify_function = handler;
// sig.sigev_value.sival_int = val;
sig.sigev_value.sival_ptr = val;
sig.sigev_notify_attributes = &attr;
//create a new timer.
timer_t timerid;
Ret = timer_create(CLOCK_REALTIME, &sig, &timerid);
if (Ret == 0)
{
struct itimerspec in, out;
in.it_value.tv_sec = 1;
in.it_value.tv_nsec = 0;
in.it_interval.tv_sec = interval;
in.it_interval.tv_nsec = 0;
mod_timer(timerid, sig, in, out);
}
}
void main()
{
// start_timer(1, 5);
// start_timer(2, 1);
data handler_data1 = {"Handler Data 1"};
data handler_data2 = {"Handler Data 2"};
void *data1 = &handler_data1;
void *data2 = &handler_data2;
start_timer(data1, 5);
start_timer(data2, 1);
}
You can use the alarm function to generate a signal, and the signal function to specify the handler to that signal.
Related
I want to run a C program in a specific duration. After this time the program should be terminated. I searched some documents about it but many of them use sleep function. I don't want to use it. I want to check the current time whether it is bigger than the target time in an infinite loop.
For example below code , my target time is 5 and when running time duration is bigger than the 5, the program should be terminated.
But the code causes an infinite loop. How can I solve this problem?
void thread_handler(union sigval sv) {
char *s = sv.sival_ptr;
/* Will print "5 seconds elapsed." */
puts(s);
}
int main(void) {
char info[] = "5 seconds elapsed.";
timer_t timerid;
struct sigevent sev;
struct itimerspec trigger;
struct itimerspec triggerAfter;
memset(&sev, 0, sizeof(struct sigevent));
memset(&trigger, 0, sizeof(struct itimerspec));
sev.sigev_notify = SIGEV_THREAD;
sev.sigev_notify_function = &thread_handler;
sev.sigev_value.sival_ptr = &info;
timer_create(CLOCK_REALTIME, &sev, &timerid);
trigger.it_value.tv_sec = 5;
timer_settime(timerid, 0, &trigger, NULL);
timer_gettime(timerid,&trigger);
while (1) {
if ((int)trigger.it_value.tv_sec > 5) { //checking the current time is bigger than the target time, it it is then exit from the program
timer_delete(timerid);
exit(0);
}
}
}
If you want to check and compare in a busy loop, you can simply call clock_gettime and completely avoid timers.
The whole point of a timer is to avoid such busy loops.
In your case your main thread can simply pause and you can exit from the thread_handler function, which is run
on a dedicated thread by the timer handler.
#include <time.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
void thread_handler(union sigval sv) {
char *s = sv.sival_ptr;
/* Will print "5 seconds elapsed." */
puts(s);
exit(0);
}
int main(void) {
char info[] = "5 seconds elapsed.";
timer_t timerid;
struct sigevent sev;
struct itimerspec trigger;
struct itimerspec triggerAfter;
memset(&sev, 0, sizeof(struct sigevent));
memset(&trigger, 0, sizeof(struct itimerspec));
sev.sigev_notify = SIGEV_THREAD;
sev.sigev_notify_function = &thread_handler;
sev.sigev_value.sival_ptr = &info;
if(0>timer_create(CLOCK_REALTIME, &sev, &timerid)) return perror("timer_create"),1;
trigger.it_value.tv_sec = 5;
if(0>timer_settime(timerid, 0, &trigger, NULL)) return perror("timer_settime"),1;
pause();
}
If you still want to busy check, you need to have the timer_gettime in the waiting loop. Calling it just once won't make the trigger object auto-update on its own.
It is very strange that bufferevent_write doesn't trigger EV_READ on the partner if bufferevent_write is called in another thread.
I prepare a simplified program to reproduce the strange result.
bufferevent_write in timeout callback immediately trigger EV_READ on the partner. but bufferevent_write running in another thread doesn't immediately trigger EV_READ on the partner. instead do_read is called just before timeout event.
Could someone help fix the problem.
Thanks a lot.
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include <event2/bufferevent.h>
#include <event2/event.h>
#define BUF_BODY "hello world\n"
void thr_fn( void * pArg )
{
struct bufferevent *pBufEv = (struct bufferevent *)pArg;
while (1)
{
// write doesn't trigger EV_READ event on the partner.
bufferevent_write(pBufEv, BUF_BODY, strlen(BUF_BODY) + 1);
printf("write\n");
sleep(5);
}
}
void do_read( struct bufferevent * pBEv, void * pArg )
{
char buff[1024];
bufferevent_read(pBEv, buff, 1024);
puts(buff);
return;
}
static void
ev_timeout_cb (evutil_socket_t sock_fd, short events, void *ctx)
{
struct bufferevent * pBufEv = (struct bufferevent * )ctx;
puts("ev_timeout_cb ...\n");
// write immediately trigger EV_READ event on the partner.
//bufferevent_write(pBufEv, BUF_BODY, strlen(BUF_BODY) + 1);
}
int main( void )
{
struct event_base * pEventBase = NULL;
struct bufferevent * aPair[2] = {NULL};
// evthread_use_pthreads();
pEventBase = event_base_new();
int nRet = bufferevent_pair_new(pEventBase, 0, aPair);
bufferevent_setcb(aPair[0], do_read, NULL, NULL, NULL);
bufferevent_enable(aPair[0], EV_READ);
pthread_t tid;
pthread_create(&tid, NULL, thr_fn, aPair[1]);
struct timeval tv = {10, 0};
evtimer_add(event_new(pEventBase, -1, EV_PERSIST, ev_timeout_cb, aPair[1]), &tv);
event_base_dispatch(pEventBase);
return 0;
}
I have to do for University a project about UDP, where i have to guarantee reliable communication; for packets, i want use timer_gettime() and timer_Settime() functions, because i can queue signals and i can associate to them a timer; in particular, struct sigevent has a field which union sigval where i can pass value to handler when signal arrived; I would like to take advantage of this passing to handler number of packets for which timer expired; I have a problem, and I've done a simple program to verify this; when I start timer, i can disarm it setting it_value of struct sigevent to 0; but data doesn't change; if I send 100 signal, header receives only data of first signal. This is my code:
#include <signal.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
int d;
void err_exit(char* str)
{
perror(str);
exit(EXIT_FAILURE);
}
void sighandler(int sig, siginfo_t *si, void *uc)
{
(void) sig;
(void) uc;
d = si->si_value.sival_int;
}
void handle_signal(struct sigaction* sa)
{
sa->sa_flags = SA_SIGINFO;
sa->sa_sigaction = sighandler;
sigemptyset(&sa->sa_mask);
if (sigaction(SIGRTMAX,sa,NULL) == -1)
err_exit("sigaction");
}
void create_timer(struct sigevent* sev,timer_t* timer_id,int i)
{
union sigval s;
s.sival_int = i;
printf("value: %d\n",i);
sev->sigev_notify = SIGEV_SIGNAL;
sev->sigev_signo = SIGRTMAX;
sev->sigev_value = s;
timer_create(CLOCK_REALTIME,sev,timer_id);
}
void set_timer(timer_t timer_id,struct itimerspec* ts)
{
if(ts == NULL)
printf("itimerspec null\n");
if (timer_settime(timer_id, 0, ts, NULL) == -1){
printf("errno code: %d\n",errno);
err_exit("timer_settime");
}
}
void initialize_timerspec(struct itimerspec* ts)
{
ts->it_value.tv_sec = 2;
ts->it_value.tv_nsec = 5;
ts->it_interval.tv_sec = 0;
ts->it_interval.tv_nsec = 0;
}
void reset_timer(timer_t timer_id, struct itimerspec* ts)
{
ts->it_value.tv_sec = 0;
ts->it_value.tv_nsec = 0;
ts->it_interval.tv_sec = 0;
ts->it_interval.tv_nsec = 0;
if (timer_settime(timer_id, 0, ts, NULL) == -1){
printf("errno code: %d\n",errno);
err_exit("timer_settime");
}
}
int main()
{
struct sigaction sa;
struct itimerspec ts[2];
struct sigevent sev[2];
timer_t timer_id[2];
handle_signal(&sa);
create_timer(sev,timer_id,0);
initialize_timerspec(ts);
set_timer(timer_id,ts);
reset_timer(timer_id,ts);
create_timer(sev + 1,timer_id + 1,1);
initialize_timerspec(ts + 1);
set_timer(timer_id,ts + 1);
printf("id1: %ju id2: %ju\n",timer_id[0],timer_id[1]);
sleep(10);
printf("d = %d\n",d);
exit(EXIT_SUCCESS);
}
I disarm first timer, and send another signal; but handler receives data associated to first signal, because it prints 0. Is there a way to send to overwrite data, sending to handler data of second signal(in this case 1)?
I have the following code:
#include <stdio.h>
#include <sys/time.h>
#include <event.h>
void say_hello(int fd, short event, void *arg){
printf("Hello\n");
}
int main(int argc, const char* argv[])
{
struct event ev;
struct timeval tv;
tv.tv_sec = 3;
tv.tv_usec = 0;
event_init();
evtimer_set(&ev,say_hello,NULL);
evtimer_add(&ev, &tv);
event_dispatch();
return 0;
}
Problem is "hello" gets printed once and then the program exits...
I want it to output "hello" indefinitely.
How to do this? Many thanks in advance,
Just to clarify Basile's solution:
I was confused as well until I realized that "timer" in this context refers to a single shot timer. What we need is an interval timer; which requires the EV_PERSIST flag in libevent.
struct timeval time;
time.tv_sec = 1;
time.tv_usec = 0;
event_set(&my_event, 0, EV_PERSIST, my_function, NULL);
evtimer_add(&my_event, &time);
change the code in main to read
evtimer_set(&ev,say_hello,&ev);
and make your say_hello function
void say_hello(int fd, short event, void *arg){
struct event *ev = arg;
struct timeval tv;
printf("Hello\n");
tv.tv_sec = 3;
tv.tv_usec = 0;
evtimer_add(ev, &tv);
}
Here is the example for libevent2:
#include <event2/event.h>
static int n_calls = 0;
void cb_func(evutil_socket_t fd, short what, void *arg)
{
struct event *me = arg;
printf("cb_func called %d times so far.\n", ++n_calls);
if (n_calls > 100)
event_del(me);
}
void run(struct event_base *base)
{
struct timeval one_sec = { 1, 0 };
struct event *ev;
/* We're going to set up a repeating timer to get called called 100
times. */
ev = event_new(base, -1, EV_PERSIST, cb_func, event_self_cbarg());
event_add(ev, &one_sec);
event_base_dispatch(base);
}
Did you read evtimer_set(3) man page? Please read it again.
You probably want to use the flag EV_PERSIST or call evtimer_add from your say_hello callback.
#include <stdio.h>
#include "ev.h"
static void timer_cback_caller(EV_P_ ev_timer* w, int revents)
{
const int new_timeout_in_ms = 1200; // new delay between timer ticks
printf("timer tick\n");
w->repeat = new_timeout_in_ms / 1000.;
ev_timer_again(EV_A_ w);
}
int main()
{
struct ev_loop *loop = ev_default_loop(0);
ev_timer timer;
const int start_delay_in_ms = 1000; // delay before first timer tick
const int timeout_in_ms = 1500; // delay between every timer tick
ev_timer_init(&timer, timer_cback_caller, start_delay_in_ms/1000., timeout_in_ms/1000.);
ev_timer_start(loop, &timer);
ev_run(loop, 0); // will never return
return 0;
}
More examples in libev documentation
Getting seg-fault when I run this code. I commented where I'm getting the seg-fault (in handler() function). I'm not sure, may be I'm wrapping data twice that's why or what's the problem? It's printing correctly till "start_timer" method.
#include <time.h>
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
typedef struct _data{
char *name;
}data;
struct timer_list{
void* timer_data;
unsigned long expires;
void (*function)(sigval_t);
};
volatile long int second = 0;
void handler(sigval_t val)
{
data *data_handler = val.sival_ptr;
printf("Handler: address of data: %p\n", data_handler);
printf("Handler: address of &data_handler->name: %p\n", &data_handler->name);
printf("Handler entered with value :%s\n", data_handler->name); `**//**SEG-FAULT HERE****`
}
void timer_handler(union sigval val)
{
printf(" ----- Seconds: %ld\n", ++second);
}
/* start timer with all we got as data is timer */
void start_timer(struct timer_list *timer)
{
printf("\nStart_timer...: Timer->data address: %p\n", timer->timer_data);
data *data_handler = timer->timer_data;
printf("Start_timer...: entered with value :%s\n", data_handler->name);
int Ret;
pthread_attr_t attr;
pthread_attr_init( &attr );
//pthread_t tid;
struct sched_param parm;
parm.sched_priority = 255;
pthread_attr_setschedparam(&attr, &parm);
struct sigevent sig;
sigval_t val;
val.sival_ptr = timer->timer_data;
sig.sigev_notify = SIGEV_THREAD;
sig.sigev_notify_function = timer->function;
// sig.sigev_value.sival_int = val;
sig.sigev_value = val;
sig.sigev_notify_attributes = &attr;
data *data_handler1 = (data *)val.sival_ptr;
printf("From sigval...: handler_data address: %p\n", data_handler1);
printf("From sigval...: handler_data->name address: %p\n", &data_handler1->name);
printf("From sigval...: Handler entered with value :%s\n", data_handler1->name);
//create a new timer.
timer_t timerid;
Ret = timer_create(CLOCK_REALTIME, &sig, &timerid);
if (Ret == 0)
{
struct itimerspec in, out;
in.it_value.tv_sec = timer->expires;
in.it_value.tv_nsec = 0;
in.it_interval.tv_sec = 0;
in.it_interval.tv_nsec = 0;
timer_settime(timerid, 0, &in, &out);
}
}
/* Start_timer_on: wrapping up data into one timer structure, and starting timer */
void start_timer_on(data timer_data, unsigned long expires)
{
struct timer_list *timer = (struct timer_list *)malloc(sizeof(struct timer_list)); //Problem was here ... forgot to use malloc
timer->timer_data = &timer_data;
printf("\nTimer->data address: %p\n", &timer_data);
timer->function = handler;
timer->expires = expires;
start_timer(timer);
}
/* Main */
void main()
{
data handler_data1 = {"Handler Data 1"};
//data handler_data2 = {"Handler Data 2"};
//void *data1 = &handler_data1;
//void *data2 = &handler_data2;
pthread_attr_t attr;
pthread_attr_init( &attr );
struct sched_param parm;
parm.sched_priority = 255;
pthread_attr_setschedparam(&attr, &parm);
struct sigevent sig;
sig.sigev_notify = SIGEV_THREAD;
sig.sigev_notify_function = timer_handler;
sig.sigev_notify_attributes = &attr;
//create a new timer - clock.
timer_t timerid;
timer_create(CLOCK_REALTIME, &sig, &timerid);
struct itimerspec in, out;
in.it_value.tv_sec = 1;
in.it_value.tv_nsec = 0;
in.it_interval.tv_sec = 1;
in.it_interval.tv_nsec = 0;
printf("*** *** *** Main clock starts *** *** ***\n");
timer_settime(timerid, 0, &in, &out);
printf("***** Start timer for data1 for 2 sec *****\n");
start_timer_on(handler_data1, 2);
// printf("***** Start timer for data1 for 5 sec *****\n");
// start_timer(data2, 5);
sleep(20);
}
This might be the problem. In the code below, timer_data is local to function start_timer_on. The object is destroyed as soon as the function exits. So, when accessing the name in handler, it will segfault.
void start_timer_on(data timer_data, unsigned long expires)
{
struct timer_list *timer;
timer->timer_data = &timer_data;
printf("\nTimer->data address: %p\n", &timer_data);
timer->function = handler;
timer->expires = expires;
start_timer(timer);
}
You should use void start_timer_on(data *timer_data, unsigned long expires), so that the data is not freed until main exits.