1 year ago
#384026
Cab
Why do these processes stay blocked even though the semaphore supposedly frees them?
I'm learning about synchronization with semaphores and message queues and I'm having a problem with an assignment.
I am trying to synchronize several child processes (the parent has a completely different function that is irrelevant to this question) so that when all of them get to a point they stop until everyone is ready, but when it's time to continue only one of them does.
I've made a small program simulating the code i have problems with.
Supposedly the "main" child process should receive one message per other child process and then free them so they can finish the program, however in practice only the "main" one continues.
The code i pasted does actually give me a segmentation fault, but i'm not sure if the reason is the same i had in the other project or something i overlooked whilst trying to make it similar to the original.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/ipc.h>
#include <signal.h>
#include <unistd.h>
#include <sys/msg.h>
#include <errno.h>
#include <sys/wait.h>
#include <ctype.h>
int sem, msgqueue, alive;
void childFunction(int i);
struct sembuf sopsEntrar1, sopsSalir1, sopsEntrar2, sopsSalir2;
union semun{
int val;
struct semid_ds *buf;
unsigned short *array;
}semn1, semn2;
//Message type
struct TipoDispara{
long tipo;
char dispara[2];
};
struct TipoDispara td, tenv;
int main(int argc, char *argv[]){
/*In the actual code there are checks to make sure the argvs are valid,
for the sake of this question any number higher than two will do*/
alive= atoi(argv[1]);
sopsEntrar1.sem_num=0;
sopsEntrar1.sem_op=-1;
sopsEntrar1.sem_flg=0;
sopsSalir1.sem_num=0;
sopsSalir1.sem_op=1;
sopsSalir1.sem_flg=0;
sopsEntrar2.sem_num=1;
sopsEntrar2.sem_op=-1;
sopsEntrar2.sem_flg=0;
sopsSalir2.sem_num=1;
sopsSalir2.sem_op=1;
sopsSalir2.sem_flg=0;
if((sem = semget(IPC_PRIVATE, 2, IPC_CREAT | 0600))==-1){
perror("Error al crear semaforos\n\n");
fflush(stdout);
exit -1;
}
semn1.val=1;
if(semctl(sem, 0, SETVAL, semn1)==-1){
perror("Error inicializando sem 1\n\n");
fflush(stdout);
return -1;
}
if(semctl(sem, 1, SETVAL, semn1)==-1){
perror("Error inicializando sem 2\n\n");
fflush(stdout);
return -1;
}
if((msgqueue = msgget(IPC_PRIVATE, IPC_CREAT | 0600))==-1){
perror("Error al crear buzon\n\n");
fflush(stdout);
exit -1;
}
int i;
for(i=0;i<alive;i++){
switch(fork()){
case -1:
perror("Error al hacer el fork.\n\n");
fflush(stdout);
return -1;
break;
case 0:
childFunction(i);
return 0;
break;
default:
/*In the actual program it does something, here i'll make it sleep a few seconds
to give the child processes some time before ending*/
if(i=(alive-1)){
sleep(10);
if(semctl(sem, 0, IPC_RMID)==-1){
printf("Error liberando semáforo\n");
fflush(stdout);
}else{
printf("\n\n\nSemaforo liberado.\n\n");
fflush(stdout);
}
if(msgctl(msgqueue, IPC_RMID, NULL)==-1){
printf("Error liberando buzon\n");
fflush(stdout);
}else{
printf("\n\n\nBuzon liberado.\n\n");
fflush(stdout);
}
return 1;
}
break;
}
}
}
void childFunction(int i){
td.tipo=2;
/*In the actual program the way of choosing who goes in the if and who in
the else, here the only relevant thing is that only one of the children
processes go in the int*/
if(i == 1){
/*What shoud happen is that this process waits for the rest to send a
message, one msgrcv per process that's supposed to send a message*/
int j;
for(j=1;j<alive;j++){
if(msgrcv(msgqueue,&td, sizeof(td)-sizeof(long),2,0)){
perror("error recibiendo mensajes");
fflush(stdout);
exit -1;
}
}
/*After going through every message, frees the other processes,
meaning every process alive but itself*/
semop(sem, &sopsSalir2, (alive-1));
}else{
strcpy(td.dispara, "SI");
if(msgsnd(msgqueue,&td, sizeof(td)-sizeof(long),0)){
perror("error enviando mensaje");
fflush(stdout);
exit (-1);
}
/*After sending the message indicating they've arrived they wait for
the "main" process to receive every message and free them*/
semop(sem, &sopsEntrar2, 1);
}
printf("\nI'm process %d\n\n", i);
}
c
semaphore
0 Answers
Your Answer