Skip site navigation (1)Skip section navigation (2)
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>