From: Jim Jagielski Date: Sat, 1 Apr 2006 02:26:57 +0000 (+0000) Subject: Extend the output routine to ensure full writes X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=37913483e06f0ba83a0b922e7f38e78a6b246a6b;p=thirdparty%2Fapache%2Fhttpd.git Extend the output routine to ensure full writes git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/fcgi-proxy-dev@390571 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/proxy/mod_proxy_fcgi.c b/modules/proxy/mod_proxy_fcgi.c index 7c89aa0adcd..94911889dfc 100644 --- a/modules/proxy/mod_proxy_fcgi.c +++ b/modules/proxy/mod_proxy_fcgi.c @@ -152,14 +152,66 @@ static void fill_in_header(fcgi_header *header, static apr_status_t send_data(proxy_conn_rec *conn, struct iovec *vec, int nvec, - apr_size_t *len) + apr_size_t *len, + int blocking) { - apr_status_t rv = apr_socket_sendv(conn->sock, vec, nvec, len); + apr_status_t rv = APR_SUCCESS, arv; + apr_size_t written = 0, to_write = 0; + int i, offset; + apr_interval_time_t old_timeout; + apr_socket_t *s = conn->sock; + + if (!blocking) { + arv = apr_socket_timeout_get(s, &old_timeout); + if (arv != APR_SUCCESS) { + return arv; + } + arv = apr_socket_timeout_set(s, 0); + if (arv != APR_SUCCESS) { + return arv; + } + } - if (rv == APR_SUCCESS) { - conn->worker->s->transferred += *len; + for (i = 0; i < nvec; i++) { + to_write += vec[i].iov_len; + } + + offset = 0; + while (to_write) { + apr_size_t n = 0; + rv = apr_socket_sendv(s, vec + offset, nvec - offset, &n); + if (rv != APR_SUCCESS) { + break; + } + if (n > 0) { + written += n; + if (written >= to_write) + break; /* short circuit out */ + for (i = offset; i < nvec; ) { + if (n >= vec[i].iov_len) { + offset++; + n -= vec[i++].iov_len; + } else { + vec[i].iov_len -= n; + vec[i].iov_base += n; + break; + } + } + } + if (rv != APR_SUCCESS) { + break; + } } + conn->worker->s->transferred += written; + *len = written; + + if (!blocking) { + arv = apr_socket_timeout_set(s, old_timeout); + if ((arv != APR_SUCCESS) && (rv == APR_SUCCESS)) { + return arv; + } + } return rv; } @@ -200,7 +252,7 @@ static apr_status_t send_begin_request(proxy_conn_rec *conn, int request_id) vec[1].iov_base = abrb; vec[1].iov_len = sizeof(abrb); - return send_data(conn, vec, 2, &len); + return send_data(conn, vec, 2, &len, 1); } static apr_status_t send_environment(proxy_conn_rec *conn, request_rec *r, @@ -335,7 +387,7 @@ static apr_status_t send_environment(proxy_conn_rec *conn, request_rec *r, vec[1].iov_base = body; vec[1].iov_len = bodylen; - rv = send_data(conn, vec, 2, &len); + rv = send_data(conn, vec, 2, &len, 1); if (rv) { return rv; } @@ -346,7 +398,7 @@ static apr_status_t send_environment(proxy_conn_rec *conn, request_rec *r, vec[0].iov_base = farray; vec[0].iov_len = sizeof(farray); - return send_data(conn, vec, 1, &len); + return send_data(conn, vec, 1, &len, 1); } enum { @@ -579,10 +631,7 @@ static apr_status_t dispatch(proxy_conn_rec *conn, request_rec *r, vec[1].iov_base = writebuf; vec[1].iov_len = writebuflen; - /* XXX This should be nonblocking, and if we don't write all - * the data we need to keep track of that fact so we can - * get to it next time through. */ - rv = send_data(conn, vec, 2, &len); + rv = send_data(conn, vec, 2, &len, 0); if (rv != APR_SUCCESS) { break; } @@ -596,7 +645,7 @@ static apr_status_t dispatch(proxy_conn_rec *conn, request_rec *r, vec[0].iov_base = farray; vec[0].iov_len = sizeof(farray); - rv = send_data(conn, vec, 1, &len); + rv = send_data(conn, vec, 1, &len, 1); } }