Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Odd Results Using timer & signals

Posted on 2004-10-24
9
Medium Priority
?
330 Views
Last Modified: 2010-04-15

First I need to say that is has been 10+ years since I wrote any serious C code, mainly because I have been doing sysadmin stuff and Java since then but trying to dig back in now. I am playing around with some code that will incorporate a timer that will be used to run various tasks at various intervals. Here is the code:

#include "sa_watchdog.h"

int count   = 0;
long millis  = 0;
char timestr[40];
struct itimerval   timer;
struct timeval currtime;
struct timeval *currtimeptr = &currtime;
struct tm *disptime;

void a_handler(int signo)
{
        gettimeofday(&currtime, NULL);
        disptime = localtime(&currtime.tv_sec);
        strftime(timestr, sizeof(timestr), "%H:%M:%S", disptime);
        millis = currtime.tv_usec / 1000;
        printf("\nSignal %d received at %s.%03ld\n", count, timestr, millis);
        count++;
}

int main()
{
          int keep_running = 1;
          int index = 0;
          timer.it_interval.tv_sec = 0;
          timer.it_interval.tv_usec = 1000000;
          timer.it_value.tv_sec = 0;
          timer.it_value.tv_usec = 1000000;

          task = task1;
          setitimer(ITIMER_REAL, &timer, NULL);
          signal(SIGALRM, a_handler);

          while(keep_running){
              index++;
              printf(".");
              if (index >= 100000000) // just wanna spin to waste time
                keep_running = 0;
          }
         
          printf("Received a total of %d signals during execution.\n", count);
          return 0;
}

However, I get some out output when I run this:
delta:/projects/SAWatchDog #./sa_watchdog  | grep -i signal
Signal 0 received at 14:44:04.069
Signal 0 received at 14:44:04.069
Signal 2 received at 14:44:07.072
Signal 2 received at 14:44:07.072
Signal 5 received at 14:44:10.074
Signal 5 received at 14:44:10.074
Signal 7 received at 14:44:13.077
Signal 8 received at 14:44:14.078
Signal 8 received at 14:44:14.078
Signal 10 received at 14:44:16.079
Signal 10 received at 14:44:16.079

2 things: 1) Why is it printing 2 lines for each signal and 2) why are the intervals only 3 seconds apart.

If I change my main while loop to this:
          int max_count = 20;
          while(keep_running){
              if (count >= max_count)
                keep_running = 0;
          }

I get this for my output:
delta:/SAWatchDog #./sa_watchdog
Signal 0 received at 14:50:38.609
Signal 1 received at 14:50:39.610
Signal 2 received at 14:50:40.611
Signal 3 received at 14:50:41.612
Signal 4 received at 14:50:42.612
Signal 5 received at 14:50:43.613
Signal 6 received at 14:50:44.614
Signal 7 received at 14:50:45.615
Signal 8 received at 14:50:46.616
Signal 9 received at 14:50:47.617
Signal 10 received at 14:50:48.618

This is what I would expect from the code above. I'm sure it is something obvious and dumb on my part but just can't seem to track it down. The platform is Fedora Core 2 using gcc 3.3.3.

Also, if anyone knows any good resources I can use for something like this please let me know.

Thanks for any help!
rhugga
0
Comment
Question by:rhugga
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
9 Comments
 
LVL 8

Assisted Solution

by:ssnkumar
ssnkumar earned 120 total points
ID: 12398337
Hi rhugga,

I tried the same code on Linux box.
It is not giving 2 displays!
And I have commented out  the line:
>task = task1;
What is this one doing?

-ssnkumar
0
 
LVL 8

Assisted Solution

by:ssnkumar
ssnkumar earned 120 total points
ID: 12398406
I tried your code on my system again.
I am not getting 2 displays.
Also, the time gap is 1 second.

This is what man page has to say regarding this: Timers  will  never  expire before the requested time, instead expiring some short, constant time afterwards, dependent  on  the  system  timer resolution  (currently 10ms).

So, your system timer resolution should be different.

>Also, if anyone knows any good resources
Tell me what is the resource you are looking for? Is it for timer or signals?

-ssnkumar
0
 
LVL 22

Assisted Solution

by:grg99
grg99 earned 60 total points
ID: 12399491
Please print out the "signo" inside the handler.

Also check the man pages for setitimer and signal, make sure your function prototypes are exactly as required.

Also try setting the sec field to "1" and the usec field to "0".

Not to mention check the function return values.



0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 5

Accepted Solution

by:
van_dy earned 195 total points
ID: 12399708
first off all, stdio functions are not async-signal-safe.
this is so because various implementations
of stdio use global data structures in non-reentrant
way. so it is reccommended not to use printf() inside
a signal handler. having said that, we can still implement what
you are trying to do by using setjmp/longjmp (both of which are
signal safe).

consider the following:
#include <setjmp.h>
#include "sa_watchdog.h"

jmp_buf     jbuf;

void a_handler(signo)
                  int signo;
{
           count++;
            longjmp(jbuf, 1);
}

...

int main()
{
        .....
              while(keep_running){
                          index++;
//                          printf(".");                dont need this
                           if(setjmp(jbuf)){
                                      gettimeofday(&currtime, NULL);
                                      disptime = localtime(&currtime.tv_sec);
                                      strftime(timestr, sizeof(timestr), "%H:%M:%S", disptime);
                                       millis = currtime.tv_usec / 1000;
                                       printf("\nSignal %d received at %s.%03ld\n", count, timestr, millis);
                           }
                            if (index >= 100000000) // just wanna spin to waste time
                                  keep_running = 0;
              }
....


hope this helps,
van_dy

0
 
LVL 1

Author Comment

by:rhugga
ID: 12400529

The task = task1 is just leftover code from earlier testing. This code is just a simple test of the timer capabilities to see if it can even perform as I need it to. The actual end-product will be nothing like this. I have never played with timers before in C so I just wanted to get an idea of how accurate they were, also how accurate they were on a heavily loaded system. I just need a timer that can be accurate to 100ms.

About the printf in the handler, this handler will eventually only contain 1 or 2 function calls but these functions will be communicating with databases and other nodes via TCP, as well as logging various things. Is printf safe to use in a function called from a handler?

Also, in refernce to the resources I was asking about, I am looking for anything that can assist me in writing a timer driven event system. This code will also be heavily threaded. I have found a lot on the web but mostly just rudimentary examples.

One last thing. Suppose I have a real-time timer that will expire every 10 secs, however the process loses its time slice on the cpu in 5 secs and doesnt regain another slice for 30 seconds (hypothetically). Thus it will be sleeping when the timer expires (it will be sleeping during the next 3 time expirations), so what happens when the process regains execution time? Are the signals queued up and sent at that time, or are they lost, or what?

Thanks for all the help, I will increase points if this is a larger problem.

Thanks,
rhugga
0
 
LVL 8

Expert Comment

by:ssnkumar
ID: 12407541
You are trying to set a real-time clock on a non-realtime system!
Because of scheduling and context-switching, you may never get a very accurate timer on these systems.

-ssnkumar
0
 
LVL 5

Expert Comment

by:van_dy
ID: 12408090
>>Is printf safe to use in a function called from a handler?

No it is not safe, signal handlers are supposed to do only trivial things, like setting
a flag, or doing somethng to a global variable.

 >>Are the signals queued up and sent at that time, or are they lost, or what?
usually, the implementation of signals is roughly like this: if the kernel has to send  a signal to
a process it sets a flag for a particullar signal in some internal data structure for the process(struct proc).
once set, this flag remains set unless the signal is handled, if the signal is not handled and there is another
occurrence of the signal, it is lost, (the signal flag is already set, you cant set it more than once).
You might consider reading about posix real time signals for what are you trying.
0
 
LVL 16

Expert Comment

by:PaulCaswell
ID: 12423940
>>No it is not safe, signal handlers are supposed to do only trivial things, like setting
>>a flag, or doing somethng to a global variable.
This is VERY good advice.

The approach I've used many times is to use signals to state switch a state machine. Then add a tight loop that just watches for a state change and semaphores the timer. Remember to protect the state machine from being switched too fast.

E.G.

// On Signal.
...
if ( State->handled )
{
  State = State->next;
  State->handled = false;
}
...

// Your state loop.
while ( true )
{
  if ( !State->handled )
  {
    (*State->Handle)();
    State->Handled = true;
  }
}

This makes:

1. Signal handling extremely trivial.
2. Versatile timer-driven coding.
3. Thread-safe if you code it right.

Paul
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.

604 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question