0

I have a server program that spawns keepalive threads for each of newly created clients. I have implemented keepalive mechanism using clock(). If just one client is connected to the server, everything works just fine.

The problem happens when I try to connect (not exactly CONNECT, its UDP) multiple clients to the server. Just after the second client connects to the server, both clients/ one of the clients get timed out for no reason, ie. before its actually timed out.

Since there are multiple clients, I am pushing updated clock time (updated whenever server receives keepalive packet from client), to a map (one entry for each client). Also in the timer logic, I need to get updated clock time from the map each time. To debug this, I added a printf in timer logic. And alas! To my surprise everything works just fine with this printf!! I am not able to figure out why. Any help is appreciated. Thanks.

....
....
pthread_t thread_id[100];
int thread_no =0;
..
//thread listening for commands from client
while(1)
{
..
    if(strcmp(cmd_cli, "1") == 0)
    {
      ..

       //this is how I spawn keepalive threads
       pthread_create(&thread_id[thread_no], NULL, timer_fun, mac_addr);
            thread_no++;    
      ..
     }
     ..
     else if(strcmp(cmd_cli, "13") == 0)
{
// Kepalive received from client
if(this_client.state >= RUN)
{
    //update timer
    this_client.start = clock();
    insert(t, mac_addr, this_client);
            ...
 ..
}
....
....

//keepalive thread handler on server
struct client_params details = lookup(t, mac);

details.start = clock();    
insert(t, mac, details);

int sec=0, delay=8;

do
{ 
    struct client_params details = lookup(t, mac);
    clock_t difference = clock() - details.start;
    sec = difference / CLOCKS_PER_SEC; 

    // following printf saves the timer
    printf("sec = %d\n", sec);
}while ( sec < delay );

details.state = TIMEOUT;

insert(t, mac, details);
....
....
....
Athul Sukumaran
  • 360
  • 4
  • 16

2 Answers2

1

Could be because the '\n' causes printf to flush the buffer and takes extra time allowing your stuff to finish. To test, comment out the printf and add a sleep() call for a good deal longer than your timeout and see if it works. Could also remove the newline from printf to avoid the buffer flush and see if it breaks again.

If that works, then you could just extend your timeout duration, add the sleep() call, or find a different synchronization mechanism.

You could use wait() if you are comfortable with signals and only plan to use posix on linux, but you'd have to coordinate your threads in a different way.

Additional Information: From IBM

If you use the system() function in your program, do not rely on clock() for program timing, because calls to system() may reset the clock.

In a multithread POSIX C application, if you are creating threads with a function that is based on a POSIX.4a draft standard, the clock() function is thread-scoped.

Double edit: never mind, I see your sec is an int, not shared. It is worth noting the system() call to avoid, though I don't see it here.

Community
  • 1
  • 1
Jon Koelzer
  • 350
  • 2
  • 9
  • Thanks. I tried removing "\n", it breaks. Do you mean to say wait() waits till system call clock() finishes its work? – Athul Sukumaran Aug 09 '19 at 07:10
  • Oh, I'm sorry- I meant sleep() (it's been a while since I've used posix calls). I will correct that now. And I did not mean sleep() is the answer, but rather if sleep(10) causes it to work, then either your timeout is too short or you need a different synchronization mechanism. It sounds like you simply need a few extra milliseconds to complete the work. – Jon Koelzer Aug 09 '19 at 07:15
  • What other timing mechanism can I use? As you can see, I need to reset it everytime I receive a keepalive packet from the client – Athul Sukumaran Aug 09 '19 at 08:35
  • @AthulSukumaran Why is your keepalive thread delay set to 8? According to wikipedia, it should be “set to no less than 2 Hours” https://en.m.wikipedia.org/wiki/Keepalive – Jon Koelzer Aug 09 '19 at 18:31
  • This is not TCP or HTTP keepalive, this is keepalive used in CAPWAP protocol – Athul Sukumaran Aug 12 '19 at 04:46
0

clock() was the culprit causing the whole issue. clock() measures CPU time used by the process. Since I am spawning multiple timer threads in this process, CPU time becomes considerably less. As a result, clock() returns a lesser value. But using printf() with "\n" increases the CPU time to exactly what is needed and thus the issue is not observable.

Athul Sukumaran
  • 360
  • 4
  • 16