J'écris un programme pour une affectation où un parent joue connect quatre contre N processus enfants. Le programme utilise des tuyaux pour communiquer les mouvements de jeu entre les processus.Race Condition avec fork() et pipe()
J'ai cependant un problème pour corriger une condition de concurrence présente dans mon programme. Il y a une condition où le processus fils bloque son appel read() une fois le jeu terminé. Cela semble seulement se produire lorsqu'il y a plus d'un processus enfant.
J'ai essayé plusieurs choses, telles que les sémaphores nommés, mais je suis encore assez nouveau pour les forks, les pipes, et l'IPC. J'ai posté un point essentiel avec le code pertinent (j'ai essayé de nettoyer le mieux que je peux pour une meilleure lisibilité) ici:
Toute aide serait grandement appréciée
EDIT
Voici la source pertinente de l'essentiel avec les déclarations ajoutées.
int main (int argc, char const *argv[])
{
int dimension = 8, children = 2, i;
int child_play_to_win = 0;
int fd[children][4];
pid_t childpid[children];
Board** boards = (Board**) malloc(sizeof(Board*) * children);
GameMove* lastMove, *tmpMove;
char buf[80];
for(i = 0; i < children; i++) {
generate_board(&(boards[i]), dimension);
int tmp[2];
pipe(tmp);
// child read
fd[i][0] = dup(tmp[0]);
// parent write
fd[i][1] = dup(tmp[1]);
pipe(tmp);
// parent read
fd[i][2] = dup(tmp[0]);
// child write
fd[i][3] = dup(tmp[1]);
childpid[i] = fork();
if(childpid[i] == -1) {
perror("fork");
exit(1);
}
if(childpid[i] == 0) {
srand(getpid());
close(fd[i][1]);
close(fd[i][2]);
while(!boards[i]->finished) {
// Read in move from parent
printf("child[%d] about to read\n", getpid());
read(fd[i][0], &buf, sizeof(GameMove));
// repeat parent move on this board
if(gameNotFinished) {
// make child move
// write move back to parent
write(fd[i][3], lastMove, sizeof(GameMove));
// If the board is finished (there was a win),
if (!gameNotFinihsed) {
// Child wins
close(fd[i][0]);
close(fd[i][3]);
printf("child[%d] ending\n", getpid());
break;
}
}
else {
// Parent won
close(fd[i][0]);
close(fd[i][3]);
break;
}
}
dealloc(boards[i]);
exit(0);
}
}
// When this hits children amount, all games are done
int games_complete = 0;
// Make first move to all children
for (i = 0; i < children; i++) {
close(fd[i][0]);
close(fd[i][3]);
lastMove = placePieceAtBestPosition(boards[i], 1);
printf("parent writing to child[%d]\n", childpid[i]);
write(fd[i][1], lastMove, sizeof(GameMove));
}
while (games_complete != children) {
for (i = 0; i < children; i++) {
// Read move from child
read(fd[i][2], &buf, sizeof(GameMove));
// repeat child move
// Check for a child win...
if (!checkForWin(boards[i], 2)) {
// No win yet, place piece at best position
lastMove = placePieceAtBestPosition(boards[i], 1);
// check for win again
boards[i]->finished = checkForWin(boards[i], 1);
// Write move back to child
write(fd[i][1], lastMove, sizeof(GameMove));
// If we won, close everything up and increment
// the games_complete counter.
if(boards[i]->finished) {
close(fd[i][1]);
close(fd[i][2]);
games_complete++;
}
} else {
// write back child move if there was a win
write(fd[i][1], lastMove, sizeof(GameMove));
close(fd[i][1]);
close(fd[i][2]);
printf("Parent lost!):\n");
games_complete++;
}
}
}
S'il vous plaît poster (parties pertinentes) code directement dans votre question, non pas par un lien. Merci. –
La première chose qui me frappe est que vous n'avez pas besoin de ces appels 'dup' après avoir créé les tuyaux. Surtout que vous ne fermez pas les descripteurs de fichiers d'origine. Selon le nombre de processus enfants que vous créez, cela peut remplir la table des descripteurs de fichiers. –
* Pourquoi associeriez-vous plus de 100 lignes de code et n'incluriez pas la déclaration de la fonction d'ouverture en haut du fichier source? – WhozCraig