How poll deal with closed pipe

2019-08-21 23:45发布

问题:

I want to konw:

When a pipe close , what status poll will set for the pipe's file descriptor?

I try the code below, After child process close all file descriptor , the poll just think all file descriptor can read! Is that right? Or just I make some mistake in this code?

I use SUSE and gcc .

#include <stdio.h>
#include <unistd.h>
#include "../../../myInclude/apue.h"// this is ok

#include <sys/poll.h>

int main(int argc, char **argv)
{
    int fd1[2]; int fd2[2]; int fd3[2];
    pid_t pid;
    if(pipe(fd1)<0 ||pipe(fd2)<0 ||pipe(fd3) <0)
        err_sys("pipe error");//this is a error deal function .it will exit the program and print error message.
    if((pid = fork()) <0)
        err_sys("fork() error");
    else if(pid == 0)
    {
        close(fd1[0]);
        close(fd2[0]);
        close(fd3[0]);

        if(write(fd1[1],"hello fd1 write!",17)!= 17)
            err_sys("write 1error ");
        sleep(2);
        if(write(fd2[1],"hello fd2 write!",17)!=17)
            err_sys("write 2error");
        sleep(2);
        if(write(fd3[1],"hello fd3 write!",17)!= 17)
            err_sys("write 3error");
        sleep(2);
        close(fd1[1]);
        close(fd2[1]);
        close(fd3[1]);
    }
    else
    {
        close(fd1[1]);
        close(fd2[1]);
        close(fd3[1]);
        struct pollfd fd[3];
        fd[0].fd = fd1[0];
        fd[1].fd = fd2[0];
        fd[2].fd = fd3[0];
        fd[0].events = POLLIN;
        fd[1].events = POLLIN;
        fd[2].events = POLLIN;
        while(poll(fd,3,3000) >0)
        {
            printf("now I come \n");
            int i = 0,n;
            char line[MAXLINE];
            for(; i< 3; i++)
            {
                if(fd[i].revents = POLLIN)
                        if ((n =read(fd[i].fd,line,MAXLINE))< 0)
                            err_sys("read error : %d",i);
                        else
                        {
                            line[n] = 0;
                            printf("read from pipe %d : %s\n",i,line);
                        }
            }
        }
        close(fd1[0]);
        close(fd2[0]);
        close(fd3[0]);
    }

    return 0;
}

I think after the child process close all write file descriptor , the poll will set the revents POLLHUP .But it just set it POLLIN !

I am reading the book .I know this an old book. So I want to know how poll works now? Is it set POLLIN for close pipe ? Or just because Linux? Or my code is wrong?

回答1:

You should always compile your programs with the -Wall option (at least). That would have told you about this problem:

if(fd[i].revents = POLLIN)

The condition will always be true because that is an assignment, not a comparison, and POLLIN is non-zero. The following would not be correct either, although it's better:

if(fd[i].revents == POLLIN)

That will be true if POLLIN is the only flag set in revents. Perhaps that's what you thought you wanted to check, but the normal test would be:

if(fd[i].revents & POLLIN)

which will check if the POLLIN bit is set, indicating that a read won't block.

The error cases can be detected after the read fails, so it's not really necessary to check if, for example, POLLHUP is set. It's not a good idea to test POLLHUP on input sockets because the flag may be set even if data is available to read, and it's usually desirable to read the data.



回答2:

When the writing end of the pipe is closed, the reading end will appear "readable" to select() and poll() - this is because a read() will not block.

When you call read(), the return value will be zero, which indicates end-of-file.



标签: c linux pipe