7

This code is part of my OS project, the project asks to make something where apply concurrent processes, I decided to make a client server poker project with two players where I use sons and grandson processes to determinate the hand value.

The scheme applied in the code is the follow:

1

The problem with the code is that in the same game only the first hand is correctly evaluated, infact the second is incorrect and in the third game there is an error and the program ends, this happens for every new game

Here's the code:

void check_hand(int suits[5],int ranks[5],int *point){

    pid_t son[2];
    int i,j;

    for (i = 0; i < 2; i++){
            son[i]=fork();

    /***********************************************
            straight flush son
    ************************************************/

            if(son[i]==0 && i==0){
                    pid_t grandson[3];
                    int k;
                    for(k=0;k<3;k++){
                            grandson[k]=fork();
                            if(grandson[k]==0 && k==0){
                                    exit(F_highcard(ranks));
                            }
                            else if(grandson[k]==0 && k==1){
                                    exit(F_flush(suits));
                            }
                            else if(grandson[k]==0 && k==2){
                                    exit(F_straight(ranks));
                            }
                            else if(grandson[k]<0){
                                    puts("fork failed");
                                    exit(-1);
                            }
                    }
                    int exit_status_straight,exit_status_flush,exit_status_highcard;
                    //waiting his sons
                    waitpid(grandson[0],&exit_status_highcard,0);
                    waitpid(grandson[1],&exit_status_flush,0);
                    waitpid(grandson[2],&exit_status_straight,0);

                    /**checkpoint A****/

                    //elaborate the exit statuses and exit with a value
            }

    /***********************************************
                    full house son
    ************************************************/


            if(son[i]==0 && i==1){
                    pid_t grandson[2];
                    int k;
                    for(k=0;k<2;k++){
                            grandson[k]=fork();
                            if(grandson[k]==0 && k==0){
                                    exit(F_n_pairs(ranks));
                            }
                            else if(grandson[k]==0 && k==1){
                                    exit(F_tris_poker(ranks));
                            }
                            else if(grandson[k]<0){
                                    exit(-1);
                            }
                    }

                    int exit_status_pair,exit_status_tris_or_poker;
                    waitpid(grandson[0],&exit_status_pair,0);
                    waitpid(grandson[1],&exit_status_tris_or_poker,0);

                    /**checkpoint B****/

                    //elaborate the exit statuses and exit with a value
                    }
            }
            if(son[i]<0){
                    puts("fork failed");
                    exit(-1);
            }
    }

    /***********************************************
            analysis exit status of his 2 sons
    ************************************************/
    pid_t pid;
    int status;
    int values[10];
    //initialization
    for(j=0;j<10;j++)values[j]=0;

    for(j=0;j<2;j++ ){
            pid = wait(&status);
            if(pid==son[0]){
                    values[WEXITSTATUS(status)]=1;
            }
            else if(pid==son[1]){
                    values[WEXITSTATUS(status)]=1;
            }
            else if(pid==-1){
                    puts("error");
                    exit(1);
            }
    }

    for(j=9;j>=0;j--){
            if(values[j]==1)break;
    }
    *point=j;
    printf("point=%d\n",*point);
}

In the following code I put some Checkpoint to find the bug, the result during execution is for every new game the same for both player 1 and player 2:

1 hand (always correct)

 checkpoint A
 checkpoint B
 point=value

2 hand

 checkpoint A
 point=value
 checkpoint B

why this happen? The father has to wait for its son and in this case he doesn't wait

3 hand

point=-1
and exit

Thanks in advance.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
abc
  • 11,579
  • 2
  • 26
  • 51
  • when you do `fork()` you create a new process and the processes don't see the changes made to each other's memory. It looks like your algorithm is designed for shared memory, but for that you need to use threads. – Gabriel Southern Jan 25 '13 at 18:33
  • what do you mean with "the processes don't see the changes made to each other's memory"? The son and grandson processes don't make changes,they just check if there is a point and exit with a value, then the father combine the results of the exit value of its sons, that before exit have combined the exit status of their sons. – abc Jan 25 '13 at 18:46
  • okay I see your point. It looked to me like you were trying to read shared memory, but if you are only communicating with exit status that should be okay. It's hard to see exactly what's happening in that large of a code sample without being able to run it. – Gabriel Southern Jan 25 '13 at 21:53

1 Answers1

1

I got this strong feeling that your troubles are related to your last wait loop. You are only waiting twice for child processes. No matter if the returned PID is one of the chidren you are checking.

My guess is that your grandchildren are causing wait to return or a value <-1 is returned for what ever reason

The prove would be to place an else-clause in your wait-loop outputting the PID and check this PID with the PIDs of created processes.

What I'd do anyway is to change your wait loop to only increment j if one of the two sons triggered the return of the waitcall.

junix
  • 3,161
  • 13
  • 27