File 0005-propagate-client-side-errors-to-ser.patch of Package apache2-mod_fastcgi
From: Yehuda Sadeh <yehuda@hq.newdream.net>
Date: Thu, 11 Aug 2011 16:40:10 -0700
Subject: [PATCH] propagate client side errors to server
When there is a client side error before we complete processing
the headers (can happen with 100-continue), we now shut down
the socket to the server (for write), so that the server can
response with the appropriate error.
---
mod_fastcgi.c | 37 ++++++++++++++++++++++++++++++++-----
1 file changed, 32 insertions(+), 5 deletions(-)
diff --git a/mod_fastcgi.c b/mod_fastcgi.c
index c7e02cc..85c4993 100644
--- a/mod_fastcgi.c
+++ b/mod_fastcgi.c
@@ -553,6 +553,15 @@ static int set_nonblocking(const fcgi_request * fr, int nonblocking)
#endif
+static void shutdown_connection_to_fs(fcgi_request *fr)
+{
+ if (fr->fd >= 0)
+ {
+ set_nonblocking(fr, FALSE);
+ shutdown(fr->fd, SHUT_WR);
+ }
+}
+
/*******************************************************************************
* Close the connection to the FastCGI server. This is normally called by
* do_work(), but may also be called as in request pool cleanup.
@@ -878,7 +887,12 @@ static int read_from_client_n_queue(fcgi_request *fr)
{
/* set the header scan state to done to prevent logging an error
* - hokey approach - probably should be using a unique value */
- fr->parseHeader = SCAN_CGI_FINISHED;
+
+ /* actually, not setting this here, will set it later,
+ so that we can continue to read the server header if that
+ wasn't done (can happen with 100-continue), so that we
+ can send correct error to client */
+ // fr->parseHeader = SCAN_CGI_FINISHED;
return -1;
}
@@ -2021,6 +2035,7 @@ static int socket_io(fcgi_request * const fr)
pool *rp = r->pool;
int is_connected = 0;
int expect_cont = 0;
+ int client_error = 0;
dynamic_last_io_time.tv_sec = 0;
dynamic_last_io_time.tv_usec = 0;
@@ -2073,10 +2088,16 @@ static int socket_io(fcgi_request * const fr)
if (read_from_client_n_queue(fr))
{
- state = STATE_CLIENT_ERROR;
- break;
+ client_error = 1;
+ if (fr->gotCont)
+ {
+ shutdown_connection_to_fs(fr);
+ fr->eofSent = 1;
+ } else {
+ state = STATE_CLIENT_ERROR;
+ break;
+ }
}
-
if (fr->eofSent)
{
state = STATE_SERVER_SEND;
@@ -2266,7 +2287,7 @@ SERVER_SEND:
}
}
- if (FD_ISSET(fr->fd, &write_set))
+ if (FD_ISSET(fr->fd, &write_set) && !client_error)
{
/* send to the server */
@@ -2355,6 +2376,12 @@ SERVER_SEND:
break;
}
}
+
+ /* was a client side error, don't blame the server */
+ if (client_error)
+ {
+ fr->parseHeader = SCAN_CGI_FINISHED;
+ }
return (state == STATE_ERROR);
}