The code doesn't work and it goes in loop. I think the error is in the gestore method, that is a handler for SIGCHLD signals. This is the first time I use a handler to capture SIGCHLD signals. This program continue to casually extracts from 0 to argv[1] until a number appears argv[1] times. If it's not clear you can test my old program that I put at the end of question. Can you help me finding the error?
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
int a;
void gestore(int segnale);
int main(int argc, char * argv[]){
int n = atoi(argv[1]), i, pid;
int * vec;
vec = malloc((n+1)*sizeof(*vec));
memset (vec, 0, sizeof(*vec));
char * newargv[] = {argv[0], argv[1] , NULL};
for(i = 0; i < n; i++){
pid = fork();
if (pid == 0)
execve("./throw-dice", newargv, NULL);
signal(SIGCHLD, gestore);
vec[WEXITSTATUS(a)]++;
}
while(vec[i] != n){
for(i = 1; i < n+1 && vec[i] != n; i++){
if(vec[i] != 0){
pid = fork();
if (pid == 0)
execve("./throw-dice", newargv, NULL);
signal(SIGCHLD, gestore);
vec[WEXITSTATUS(a)]++;
}
}
}
printf("The value %d is appeared %d times!\n", i, vec[i]);
while (wait(&a) != -1);
free(vec);
}
void gestore(int segnale){
signal(segnale, SIG_IGN);
waitpid(WAIT_ANY, &a, WNOHANG);
signal(segnale, gestore);
}
My goal was to modify my old program (that works) changing the way I capture the exit status of childs. From syncronically with "wait" to asyncronically with a gestore method that handle SIGCHLD signals. This is my old program:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char * argv[]){
int n = atoi(argv[1]), a, i, pid;
int * vec;
vec = malloc((n+1)*sizeof(*vec));
memset (vec, 0, sizeof(*vec));
char * newargv[] = {argv[0], argv[1] , NULL};
for(i = 0; i < n; i++){
pid = fork();
if (pid == 0)
execve("./throw-dice", newargv, NULL);
wait(&a);
vec[WEXITSTATUS(a)]++;
}
while(vec[i] != n){
for(i = 1; i < n+1 && vec[i] != n; i++){
if(vec[i] != 0){
pid = fork();
if (pid == 0)
execve("./throw-dice", newargv, NULL);
wait(&a);
vec[WEXITSTATUS(a)]++;
}
}
}
printf("The value %d is appeared %d times\n", i, vec[i]);
while (wait(&a) != -1);
free(vec);
}
//throw-dice.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char * argv[]) {
int n, val;
// Must have an argument
if (argc < 2) {
exit(-1);
}
// the 1st argument must be a positive number
if ((n = atoi(argv[1])) <= 0) {
exit(-1);
}
// sleep(1); // sleep a bit
srand(getpid()); // initialize the random seed with PID
val = rand() % n + 1;
printf("(PID=%d): got number %d\n", getpid(), val);
exit(val);
}