My goal is to synchronize forked processes by a common int value.
I need to fork a number of children but also semaphore block them until all the children have been forked.
This variable (init_num
) must first become equal to the number of processes I have and then the processes can continue with their functions.
My code :
pid_t pid;
key_t key;
sem_t *sem;
sem_t *sem2;
int shmid;
int main(int argc , char* argv[])
{
if (argc < 2){
printf("Incorrect number of arguments given!\n");
exit(-1);
}
int num_strings = argc - 2;
int reps = atoi (argv[1]);
// SHARED MEMORY //
key = 9876;
shmid = shmget( key , sizeof(int) , 0644 | IPC_CREAT);
if ( shmid < 0 ){
perror("shmget\n");
exit(-1);
}
// SHARED MEMORY INITIATED //
int *init_num;
init_num = shmat ( shmid , NULL , 0);
*init_num = 0;
// SEMAPHORES TIME //
sem = sem_open("TheSem", O_CREAT | O_EXCL , 0644 , 1);
sem2 = sem_open("TheSem2", O_CREAT | O_EXCL , 0644 , 0);
// SEMAPHORE DONE //
int i;
// FORKS //
for (i=0; i<num_strings; i++){
pid = fork();
if (pid < 0) {
printf ("Fork error.\n");
sem_unlink("TheSem");
sem_close(sem);
sem_unlink("TheSem2");
sem_close(sem2);
}
else if ( pid == 0)
break;
}
// FATHER //
if ( pid !=0 && pid!=-1 ){
int status;
while(pid = waitpid (-1,NULL,0)){
if(errno == ECHILD)
break;
}
shmdt (init_num);
shmctl (shmid, IPC_RMID, 0);
sem_unlink("TheSem");
sem_close(sem);
sem_unlink("TheSem2");
sem_close(sem);
}
int n;
//CHILDREN //
if( pid == 0){
sem_wait(sem);
init();
*init_num++;
sem_post(sem);
if (*init_num < num_strings ){
sem_wait(sem2);
}else{
for(n=0 ; n <=num_strings-1; n++){
sem_post(sem2);
}
}
// DISPLAY //
for(n=0; n < reps; n++){
sem_wait(sem);
display(argv[2+i]);
sem_post(sem);
}
}
return(0);
}
And *init_num
is in shared memory space.
The problem is after all of the processes have done init()
and *init_num
should be equal to processes
my program deadlocks and stops right there.
Output :
STARTING: pid 1268, tid 1157203712
STARTING: pid 1270, tid 1157203712
STARTING: pid 1269, tid 1157203712
STARTING: pid 1271, tid 1157203712
STARTING: pid 1272, tid 1157203712
STARTING: pid 1273, tid 1157203712
STARTING: pid 1274, tid 1157203712
STARTING: pid 1275, tid 1157203712 // these are init()
Enable warnings, and you will see
warning: expression result unused [-Wunused-value]
*init_num++;
^~~~~~~~~~~
which immediately shows your problem. The children do not increment the value: they increment the pointer. Technically it is UB, but realistically they all read 0. Change it to
(*init_num)++;