]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Extend the output routine to ensure full writes
authorJim Jagielski <jim@apache.org>
Sat, 1 Apr 2006 02:26:57 +0000 (02:26 +0000)
committerJim Jagielski <jim@apache.org>
Sat, 1 Apr 2006 02:26:57 +0000 (02:26 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/fcgi-proxy-dev@390571 13f79535-47bb-0310-9956-ffa450edef68

modules/proxy/mod_proxy_fcgi.c

index 7c89aa0adcd55e9869f5198d6f4146f2818a34a3..94911889dfc7049c37567a9ee3eb9a31b41aae1b 100644 (file)
@@ -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);
             }
         }