pipe stuck in read (C - system calls)

Giuma79

This the first time for me using C and so it has been very difficult so far. My program reads a file.txt. In the first line there is the number of childs that i have to create(var: NPROC) and in the remaining lines i have to read the child's process id, two integers and a character that is the operation that i have to calculate: ex:

NPROC
(id) (n1) (op) (n2)
2
2 3 + 1
1 5 / 2
2 9 * 3

I have to send the operations (line by line) to the child using a message queue (which works perfectly) and then the child should send back the results using a pipe.

this is the code:

(father)

//other code
for(i=0; i < NPROC; i++) {

    if(pipe(p) == -1) {
        perror("pipe");
        exit(1);
    }

    switch(currentPid = fork()){
        case 0:

            execl("./child", "./child", NULL);

            return 0;
        case -1:
            printf("Error when forking\n");
            break;
        default:

            // in the father
            childrenPids[i] = currentPid; // store current child pid
            wait(NULL);

            printf("\nParentpid:  %d, Childpid: %i \n", getpid(), currentPid);

            //close(p[1]);

            if(read(p[0], &val, sizeof(val) == -1){
                perror("read()\n");
                exit(1);
            }

            printf("Parent(%d) received value: %d\n", getpid(), val);

            break;         
    }

   //other code


(child)
 //other code
 while (1) {

        long msgtype = m->mtype;
        if(msgrcv(msgid, m, sizeof(message) - sizeof(m->mtype), msgtype, IPC_NOWAIT) == -1) {
            // if(close (p[1]) == -1){
            //     perror("close p[1] of the child\n");
            // } 
            //perror("\nmsgrcv");
            exit(1);
        }
        result[i] = calcolate_results(m);
        // printf("%i %i %c %i", m->id, m->num1, m->op, m->num2);
        printf("\nresult: %i\n", result[i]);

        val = result[i];

        if(write (p[1], &val, sizeof(val)) == -1) { 
            perror("write\n");
            exit(1);
        }
        printf("Child(%d) send val: %d\n", getpid(), val);
    }
 //other code

Now my problem is that the read in the father seems not to get the message. When i execute the program doens't exit, it loops (stays stuch) at the read in the father. I tried to put the read outside the for (so it should at least read the last message) but the program still stays stuck in the read. So i would be very thankful if someone could help me.

melpomene

Your code is full of problems.

switch(currentPid = fork()){
    case 0:

Here you need to close the read end of the pipe:

        close(p[0]);

Usually you'd have a dup2 before execl here. Typically, if your child process is going to load another program, you want to redirect its stdout to the write end of the pipe, as in dup2(p[1], 1); close(p[1]);.

        execl("./child", "./child", NULL);

        return 0;
    case -1:
        printf("Error when forking\n");
        break;
    default:

        // in the father
        childrenPids[i] = currentPid; // store current child pid
        wait(NULL);

This wait call is in the wrong place. If the child outputs more data than the pipe can hold at once, you have a deadlock here (the child will block in write, waiting for the parent to read some data for the pipe before it can exit; the parent will block in wait, waiting for the child to exit before reading from the pipe).

It also doesn't make sense to wait for the child to exit before you've given it anything to do. Isn't this supposed to be a sort of coprocess-like design, i.e. the children should keep running along the parent, doing arithmetic on request and sending the results back?

        printf("\nParentpid:  %d, Childpid: %i \n", getpid(), currentPid);

        //close(p[1]);

Why is this close commented out? It's crucial that the parent process close the write end of the pipe (because otherwise reading from the read end of the pipe will block as the write end is still open somewhere (in the same process, in this case)).

        if(read(p[0], &val, sizeof(val) == -1){

This line doesn't even compile. It's missing a ).

            perror("read()\n");
            exit(1);
        }

You're missing a check for EOF. read will return 0 when it's reached the end of the data (and leave val uninitialized).

You should consume all available data from the pipe (until read returns 0), and only then waitpid(currentPid, NULL, 0);.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related