httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Roy T. Fielding" <field...@kiwi.ICS.UCI.EDU>
Subject Re: [PATCH] FreeBSD and SIGPIPE: perhaps solved?
Date Wed, 16 Apr 1997 06:42:03 GMT
>But after tracing down mod_cgi I found that the "pipewr" of the CGI program is
>the write to its stdout as expected, because it still has not received a
>SIGPIPE and still wants to do its "print STDOUT ...". BUT: The "piperd" of the
>Apache process is not the fread() from send_fd(). Actually it is the fread()
>in mod_cgi which wants to soak the stderr of the CGI script. DEAD LOOP,
>because the close of script_in is placed _after_ this fread-loop in mod_cgi!
>So the CGI waits until Apache reads more from script_in while Apache reads
>from script_err. The only solutions are either a timeout in Apache or a
>SIGPIPE for the CGI script. But the SIGPIPE will not happen until Apache does
>the close(script_in) in mod_cgi. And the timeout does also not happen.

I think what you are seeing is that the first timeout does happen -- it
stops send_fd (inside send_fd) -- and then the second timeout has yet
to be completed.

>I currently don't know (have not traced down any more) why no timeout on the
>soaking of the scripts stderr happens, but a possible workaround would be to
>interchange the order of script_err-soaking and script_in-closing. This worked
>fine here. The CGI script gets its SIGPIPE and the Apache process is not
>frozen.
>
>Here is the possible patch:
>
>*** mod_cgi.c.orig	Sun Apr  6 09:43:40 1997
>--- mod_cgi.c	Sat Apr 12 13:36:50 1997
>***************
>*** 520,536 ****
>  	
>  	send_http_header(r);
>  	if (!r->header_only)
>  	    send_fd(script_in, r);
>  
>  	/* Soak up stderr */
>  	soft_timeout("soaking script stderr", r);
>  	while ((fgets(argsbuffer, HUGE_STRING_LEN-1, script_err) != NULL) &&
>  	       !r->connection->aborted)
>  	    continue;
>  	kill_timeout(r);
>- 
>- 	pfclose (r->main ? r->main->pool : r->pool, script_in);
>  	pfclose (r->main ? r->main->pool : r->pool, script_err);
>      }
>  
>      if (nph) {
>--- 520,535 ----
>  	
>  	send_http_header(r);
>  	if (!r->header_only)
>  	    send_fd(script_in, r);
>+ 	pfclose (r->main ? r->main->pool : r->pool, script_in);
>  
>  	/* Soak up stderr */
>  	soft_timeout("soaking script stderr", r);
>  	while ((fgets(argsbuffer, HUGE_STRING_LEN-1, script_err) != NULL) &&
>  	       !r->connection->aborted)
>  	    continue;
>  	kill_timeout(r);
>  	pfclose (r->main ? r->main->pool : r->pool, script_err);
>      }
>  
>      if (nph) {
>
>I'm not sure if this is really enough to fix the problem in _a clean way_.
>Better would be if we use the above patch _AND_ make sure the timeout happens,
>too. The above patch should be ok anyway, I think (because the different order
>has no negative side effects I can think of).

Yes, the above patch is needed even if there is a timeout problem.
We probably should change the fgets to a real system call (one that
isn't automatically restarted).

....Roy  +1

Mime
View raw message