PROBLEM: poll and select report different status

From: Zhao Shuai
Date: Sat Jul 04 2009 - 06:25:32 EST


[1.] One line summary of the problem:
select and poll report different status

[2.] Full description of the problem/report:
A reader and a writer opens a fifo, then close the reader side and poll & select
on the writer side. Surprisingly, poll and select reports different
status. Poll says
the writer fd is unreadable & writable, but select says it's
readable(writer fd is
a WRITE ONLY descriptor!) & writable.

[3.] Keywords (i.e., modules, networking, kernel):
kernel

[4.] Kernel information
[4.1.] Kernel version (from /proc/version):
Linux version 2.6.24-24-generic (buildd@palmer) (gcc version 4.2.4
(Ubuntu 4.2.4-1ubuntu4))

[7.] A small shell script or example program which triggers the
problem (if possible)
see the attached file.


--
Regards,
Zhao
/*
* a reader and a writer opens fifo, then close the reader side,
* poll and select on writer fd comes to different results
*/
#include <stdio.h>
#include <stdlib.h>
#include <poll.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/stat.h>

#define FIFO_NAME "tmpfifo"

int main(int argc, char *argv[])
{
int reader_fd, writer_fd;
struct pollfd fds[1];
fd_set readfds, writefds, exceptfds;

if (mkfifo(FIFO_NAME, 0777) < 0) {
perror("mkfifo error");
return (-1);
}

reader_fd = open(FIFO_NAME, O_RDONLY | O_NONBLOCK);
if (reader_fd < 0) {
perror("read open error");
unlink(FIFO_NAME);
return (-1);
}

writer_fd = open(FIFO_NAME, O_WRONLY | O_NONBLOCK);
if (writer_fd < 0) {
perror("write open error");
unlink(FIFO_NAME);
return (-1);
}

fds[0].fd = writer_fd;
fds[0].events = POLLIN | POLLOUT | POLLERR;
fds[0].revents = 0;

FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
FD_SET(writer_fd, &readfds);
FD_SET(writer_fd, &writefds);
FD_SET(writer_fd, &exceptfds);

/* close the reader side */
close(reader_fd);

/* poll on the writer side */
if (poll(fds, 1, 0) < 0) {
perror("poll error");
unlink(FIFO_NAME);
return (-1);
}
printf("poll results: ");
if (fds[0].revents & POLLIN)
printf(" readable ");
if (fds[0].revents & POLLOUT)
printf(" writable ");
if (fds[0].revents & POLLHUP)
printf(" hang up");
if (fds[0].revents & POLLERR)
printf(" error ");
if (fds[0].revents & POLLNVAL)
printf(" invalid fd ");
printf("\n");

/* select on the writer side */
if (select(writer_fd+1, &readfds, &writefds, &exceptfds, NULL) < 0) {
perror("select error");
unlink(FIFO_NAME);
return (-1);
}
printf("select result: ");
if (FD_ISSET(writer_fd, &readfds))
printf(" readable ");
if (FD_ISSET(writer_fd, &writefds))
printf(" writable ");
if (FD_ISSET(writer_fd, &exceptfds))
printf(" exceptional ");
printf("\n");

unlink(FIFO_NAME);
return (0);
}