You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by "Roy T. Fielding" <fi...@kiwi.ICS.UCI.EDU> on 1997/04/16 08:42:03 UTC
Re: [PATCH] FreeBSD and SIGPIPE: perhaps solved?
>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