0

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;
}
Kush
  • 1
  • is the fun2() getting called at all ? could you please paste your output which has prints – Nikole Jul 20 '14 at 08:43
  • and why do you need to set sigaction in fun2() and fun3() again ? – Nikole Jul 20 '14 at 08:52
  • you might want to return from single handler every time it is called. Even if this code worked, I would get stack overflow. Not to say that printing functions aren't re-entrant... – wick Jul 20 '14 at 08:53
  • Hi Nikole, fun2() is getting called after which it is not calling fun3() as we are expect it to call. Here we are trying to simulate a scheduler which calls the different functions based on timer, when a timer expires it calls the timer_handler which call the next function based on the value of count. – Kush Jul 20 '14 at 09:32
  • The o/p is : scheduler called..calling fun1,then it prints fun1 for 250milisec and then scheduler called.. calling fun2() and then it prints fun2 infinitely. but we want it to call the fun3() and so on.This is the reason we are setting sigaction in fun2() and fun3(). – Kush Jul 20 '14 at 09:39
  • Hi wick,Here our motive is to take control from while(1) loop using signal and setitimer. sorry but i didn't get your question.could u plz repeat it. – Kush Jul 20 '14 at 09:50
  • 1
    As wick pointed out, its not safe to call printf. could you alter your code by removing print in signal handler and all func*() see this http://stackoverflow.com/questions/16891019/how-to-avoid-using-printf-in-a-signal-handler. – Nikole Jul 20 '14 at 09:53
  • I removed the printf statements from the signal handler but the o/p is same. I am wondering why only SLGALRM is generating for fun1() when the timer expires.It should behave in the same manner for fun2() too. – Kush Jul 20 '14 at 10:09
  • Why exactly do you ask, and what is the real purpose of all this? – Basile Starynkevitch Jul 20 '14 at 10:28
  • The purpose is to implement a scheduler based on signal and timer. – Kush Jul 21 '14 at 05:24

2 Answers2

2

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.

1

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.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547