Note that there are some explanatory texts on larger screens.

plurals
  1. PORace Condition with fork() and pipe()
    primarykey
    data
    text
    <p>I am writing a program for an assignment where a parent plays connect four against N child processes. The program uses pipes to communicate game moves between processes.</p> <p>I am having a problem fixing a race condition that is present in my program, however. There is a condition where the child process hangs one its read() call after the game has finished. This only seems to happen when there is more than one child process.</p> <p>I've tried several things, such as named semaphores, but I'm still pretty new to forks, pipes, and IPC. I've posted a gist with relevant code (I tried to clean it up as best as I can for readability) here: </p> <p><strong><a href="https://gist.github.com/chrisbenincasa/5101530" rel="nofollow">Gist with relevant code</a></strong></p> <p>Any help would be greatly appreciated</p> <p><strong>EDIT</strong> </p> <p>Here's the relevant source from the gist with the declarations added.</p> <pre><code>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 &lt; children; i++) { generate_board(&amp;(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]-&gt;finished) { // Read in move from parent printf("child[%d] about to read\n", getpid()); read(fd[i][0], &amp;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 &lt; 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 &lt; children; i++) { // Read move from child read(fd[i][2], &amp;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]-&gt;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]-&gt;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++; } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload