简体   繁体   中英

Reading From One Child Process Blocks Other Children

As you can see from the code I shared below, I am trying to implement 1 central server and n children. First I create all n children by forking from the server. Also, before forking I create bidirectional pipes using Pipe . Having forked and created n children, I want to read characters from child codes. They all send character 'A', but I can only read from one child. I use poll to select active children and try to read data from them. What may cause the program to block on one child? I will appreciate any help.

#define Pipe(fd) socketpair(AF_UNIX, SOCK_STREAM, PF_UNIX, fd)
int n = 5;    
struct pollfd pfd[n];

for (int i = 0; i < n; i++){
    Pipe(fd[i]);
    if (fork() == 0){
        close(fd[i][0]);
        dup2(fd[i][1], 0);
        dup2(fd[i][1], 1);
        close(fd[i][1]);
        execl(code, arguments);
    }

    else {
        close(fd[i][1]);
        dup2(fd[i][0], 0);
        dup2(fd[i][0], 1);
        close(fd[i][0]);
    }

    struct pollfd s;
    s.fd = fd[i][1];
    s.events = POLLIN;
    s.revents = 0;
    pfd[i] = s;
}   

while(1){
    poll(pfd, n, 2);
    for (int i = 0; i < n; i++){
        if (pfd[i].revents && POLLIN){
            char data;
            read(0, &data, 1);

            if (data == 'A'){ 
            .
            .
            .
            }
        }
    } 
}

You can only have one standard input file descriptor and one standard output file descriptor in the parent. Your code is like this:

for (int i = 0; i < n; i++){
    Pipe(fd[i]);
    if (fork() == 0){
        close(fd[i][0]);
        dup2(fd[i][1], 0);
        dup2(fd[i][1], 1);
        close(fd[i][1]);
        execv(code, arguments);
    }
    else {
        close(fd[i][1]);
        dup2(fd[i][0], 0);
        dup2(fd[i][0], 1);
        close(fd[i][0]);
    }
    …poll setup…
}

This carefully zaps standard input and standard output in the parent every time a child is created, leaving the program with only the connection to the last child.

You should not be using dup2() like that in the parent; you probably need to keep the file descriptors open in the array so that you use them to communicate with the children separately.

I have not reviewed why you're using subscripts [0] and [1] after fd[i] as you are, but it doesn't feel right.

You should put at minimum an exit(1); or _exit(1); after the execv() call; I'd prefer to see an error message printed to stderr too, reporting that the execv() failed. You don't need to check the return value; if execv() returns, it failed; if it succeeds, it does not return. Otherwise, if the execv() fails, you can end up with multiple processes all thinking they're the parent. That leads to chaos. Always ensure you handle failure to execute other programs!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM