Date: Wed, 18 Jun 2003 10:00:27 -0700 (PDT) From: "Artem 'Zazoobr' Ignatjev" <timon@memphis.mephi.ru> To: freebsd-bugs@FreeBSD.org Subject: Re: kern/53447: poll(2) semantics differ from susV3/POSIX Message-ID: <200306181700.h5IH0Ruw044555@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/53447; it has been noted by GNATS. From: "Artem 'Zazoobr' Ignatjev" <timon@memphis.mephi.ru> To: freebsd-gnats-submit@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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200306181700.h5IH0Ruw044555>