kern/53447: poll(2) semantics differ from susV3/POSIX
Artem 'Zazoobr' Ignatjev
timon at memphis.mephi.ru
Wed Jun 18 10:00:29 PDT 2003
The following reply was made to PR kern/53447; it has been noted by GNATS.
From: "Artem 'Zazoobr' Ignatjev" <timon at memphis.mephi.ru>
To: freebsd-gnats-submit at freebsd.org
Cc:
Subject: Re: kern/53447: poll(2) semantics differ from susV3/POSIX
Date: 18 Jun 2003 20:54:29 +0400
clemens fischer wrote:
> a colleague and i independantly made the same observation: we are
> running a wiki on a small HTTP server. every page served by it had an
> error message on the bottom: "Looks like the CGI crashed.". we could
> track this down to the code in the server where data is read from the
> CGI through a pipe. this is done using poll(2) and read(2). the same
> code runs without problems on linux, and we can patch fnord to work
> around the problem, which is otherwise reproducable.
>
> this is part of the discussion thread on the mailinglist:
>
> > i had the same problem on my freebsd-4.8-stable. every page had
> > "looks like your CGI crashed" at the bottom, but they actually
> > worked fine. after applying the patch the problem has
> > disappeared.
>
> Mhh, then this is apparently a problem with BSD poll() semantics.
>
> poll is expected to set the POLLHUP bit on EOF, but FreeBSD
> apparently does not, but signals POLLIN and then returns 0 on
> read(). Is someone involved with the FreeBSD crowd and can post a
> bug report for this?
>
FreeBSD DOES set POLLHUP bit; but, also, EOF on pipe or disconnected
socket can be caught by reading 0 bytes from ready-to-read descriptor.
See the code below (it's /sys/kern/sys_pipe.c 1.60.2.13, used in FreeBSD
4.8-RELEASE):
int
pipe_poll(fp, events, cred, p)
struct file *fp;
int events;
struct ucred *cred;
struct proc *p;
{
struct pipe *rpipe = (struct pipe *)fp->f_data;
struct pipe *wpipe;
int revents = 0;
wpipe = rpipe->pipe_peer;
if (events & (POLLIN | POLLRDNORM))
if ((rpipe->pipe_state & PIPE_DIRECTW) ||
(rpipe->pipe_buffer.cnt > 0) ||
> (rpipe->pipe_state & PIPE_EOF))
> revents |= events & (POLLIN | POLLRDNORM);
if (events & (POLLOUT | POLLWRNORM))
if (wpipe == NULL || (wpipe->pipe_state & PIPE_EOF) ||
(((wpipe->pipe_state & PIPE_DIRECTW) == 0) &&
(wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt) >= PIPE_BUF))
revents |= events & (POLLOUT | POLLWRNORM);
> if ((rpipe->pipe_state & PIPE_EOF) ||
> (wpipe == NULL) ||
> (wpipe->pipe_state & PIPE_EOF))
> revents |= POLLHUP;
if (revents == 0) {
if (events & (POLLIN | POLLRDNORM)) {
selrecord(p, &rpipe->pipe_sel);
rpipe->pipe_state |= PIPE_SEL;
}
if (events & (POLLOUT | POLLWRNORM)) {
selrecord(p, &wpipe->pipe_sel);
wpipe->pipe_state |= PIPE_SEL;
}
}
return (revents);
}
More information about the freebsd-bugs
mailing list