Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Linux signals program doesn't return the same value on each execution

I have this code:

#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
int cpt = 0;
void handler (int sig) {
     cpt++ ;
}
int main() {
  int i;
  signal(SIGCHLD, handler);
  for (i = 0; i < 5; i++) {
       if (fork() == 0) {
           exit(0);
       }
   }
   while (wait(NULL) != -1) ;
   printf("cpt = %d\n", cpt);
   return 0;
}

this program to my understanding should always print cpt = 5
but when i run it on my machine it returns different values (3,4,5) why is that?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

The SIGCHLD signal is a little funny and doesn’t work like you’d expect: we think we should get one signal per child death, but that’s not it.

Instead, it’s a kind of level-triggered thing where at some unknown intervals it sends the signal if there are any un-waited-for children.

In the loop you provided that burns through the wait(), this loop is consuming multiple children before the signal handler gets around to it, hence less trips through the handler.

Others have pointed out that you should be using a volatile sig_atomic_t variable, and though this is a good idea, it’s not why you’re seeing this behavior.

I believe the only way to get a guaranteed one-signal-per-child is to actually wait for the child in the signal handler – this makes it appear more like an edge-triggered signal.

Of course, you’re pretty limited to what you can do in the signal handler, so if your application already has a good regimen for waiting for child processes, you likely don’t need a SIGCHLD handler.

#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>

static volatile sig_atomic_t cpt = 0;

static void handler(int sig) {
     cpt++;
     wait(NULL);  // ADD ME
}

int main() {
  int i;
  signal(SIGCHLD, handler);
  for (i = 0; i < 5; i++) {
       if (fork() == 0) {
           exit(0);
       }
   }
   while (wait(NULL) != -1) ;
   printf("cpt=%d\n", cpt);
   return 0;
}

As an alternative, if the while() loop were not so tight and had other processing (or even an explicit delay), there would not be a race condition and you’d see all five SIGCHLD delivered.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading