Re: CGI-Output truncated - what does POLLHUP mean?

Gerrit Pape <[email protected]> Mon, 31 Mar 2008 08:20:57 +0000
Newsgroups gmane.comp.web.fnord
Message-ID <20080331082057.15355.qmail@85cceb4df6c355.315fe32.mid.smarden.org>
On Mon, Mar 31, 2008 at 09:59:18AM +0200, Laurent Bercot wrote:
> > You are supposed to get a POLLHUP if the pipe closed unexpectedly, i.e.
> > if there is an error on the pipe.
> 
>  It's been a few years since I've experimented with this, and newer
> kernels might have changed behaviours, but I remember getting POLLHUPs
> on Linux in some normal EOF situations.
>  It happened either with pipes or with sockets - I don't remember which
> one: when the last batch of data (followed by EOF) arrived, poll()
> returned *both* POLLIN and POLLHUP. In other situations, the last
> batch of data just triggered POLLIN, and subsequent poll()s returned
> POLLHUP.
> 
>  The workaround for me was to always handle POLLIN first, and POLLHUP
> later, in the poll() loop, so the data, if any, gets read first, and
> the connection gets closed later.
> Moving the "if (x[blah].revents & POLLHUP) break ;" line to the end
> of the loop should make things work in every case.

Hi, see
 http://bugs.debian.org/326014
I apply the patch below to Debian's fnord since 2005.

Regards, Gerrit.

---
From: Gerrit Pape <[email protected]>
Subject: [PATCH] httpd.c: don't stop but retry on revents & POLLHUP.

thx David Schweikert
 http://bugs.debian.org/326014
---
 httpd.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/httpd.c b/httpd.c
index 2d9b333..bc72875 100644
--- a/httpd.c
+++ b/httpd.c
@@ -539,7 +539,7 @@ static void start_cgi(int nph,const char* pathinfo,const char *const *envp) {
 
       while(poll(pfd,nr,-1)!=-1) {
 	/* read from cgi */
-	if (pfd[0].revents&POLLIN) {
+	if (pfd[0].revents&(POLLIN|POLLHUP)) {
 	  if (!(n=read(fd[0],ibuf,sizeof(ibuf)))) break;
 	  if (n<0) goto cgi_500;
 	  /* startup */
@@ -572,7 +572,6 @@ static void start_cgi(int nph,const char* pathinfo,const char *const *envp) {
 	    buffer_put(buffer_1,ibuf,n);
 	  }
 	  size+=n;
-	  if (pfd[0].revents&POLLHUP) break;
 	}
 	/* write to cgi the post data */
 	else if (nr>1 && pfd[1].revents&POLLOUT) {
@@ -591,7 +590,6 @@ static void start_cgi(int nph,const char* pathinfo,const char *const *envp) {
 	    close(df[1]);
 	  }
 	}
-	else if (pfd[0].revents&POLLHUP) break;
 	else {
 cgi_500:  if (startup)
 	    badrequest(500,"Internal Server Error","Looks like the CGI crashed.");
-- 
1.5.3.8